diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-20 21:08:12 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-20 21:08:12 +0000 |
commit | fc8614660ee6c0963c96925affa7d837c02e0b4b (patch) | |
tree | d81cfed376f54ed52cbf540e0aa0c3ac46bf7c2d | |
parent | a174146bf09aa549a4ae43f2b8a0f6aa638f499e (diff) | |
download | gitlab-ce-fc8614660ee6c0963c96925affa7d837c02e0b4b.tar.gz |
Add latest changes from gitlab-org/gitlab@master
37 files changed, 814 insertions, 421 deletions
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index fef456d3d19..1ce7cbaabfb 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -46,12 +46,6 @@ Lint/RedundantCopDisableDirective: Lint/UselessMethodDefinition: Enabled: false -# Offense count: 321 -# Configuration parameters: ForbiddenDelimiters. -# ForbiddenDelimiters: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$)) -Naming/HeredocDelimiterNaming: - Enabled: false - # Offense count: 218 # Cop supports --auto-correct. # Configuration parameters: PreferredName. diff --git a/.rubocop_todo/naming/heredoc_delimiter_naming.yml b/.rubocop_todo/naming/heredoc_delimiter_naming.yml new file mode 100644 index 00000000000..86d9ae2f24d --- /dev/null +++ b/.rubocop_todo/naming/heredoc_delimiter_naming.yml @@ -0,0 +1,141 @@ +--- +Naming/HeredocDelimiterNaming: + # Offense count: 388 + # Temporarily disabled due to too many offenses + Enabled: false + Exclude: + - 'app/models/ci/build_trace_chunks/redis_base.rb' + - 'app/models/concerns/counter_attribute.rb' + - 'app/models/concerns/legacy_bulk_insert.rb' + - 'app/models/trending_project.rb' + - 'app/services/ci/ensure_stage_service.rb' + - 'app/services/packages/debian/generate_distribution_key_service.rb' + - 'app/workers/concerns/limited_capacity/job_tracker.rb' + - 'config/initializers/01_secret_token.rb' + - 'ee/app/workers/update_max_seats_used_for_gitlab_com_subscriptions_worker.rb' + - 'ee/db/geo/migrate/20180322062741_migrate_ci_job_artifacts_to_separate_registry.rb' + - 'ee/db/geo/migrate/20191010204941_migrate_lfs_objects_to_separate_registry.rb' + - 'ee/lib/api/elasticsearch_indexed_namespaces.rb' + - 'ee/spec/lib/ee/gitlab/ci/config_spec.rb' + - 'ee/spec/lib/ee/gitlab/ci/templates/templates_spec.rb' + - 'ee/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb' + - 'ee/spec/lib/gitlab/elastic/search_results_spec.rb' + - 'ee/spec/lib/gitlab/patch/database_config_spec.rb' + - 'ee/spec/lib/gitlab/sitemaps/sitemap_file_spec.rb' + - 'ee/spec/services/ci/create_pipeline_service/compliance_spec.rb' + - 'ee/spec/services/ci/create_pipeline_service/dast_configuration_spec.rb' + - 'ee/spec/services/ci/create_pipeline_service/needs_spec.rb' + - 'ee/spec/services/ci/create_pipeline_service/runnable_builds_spec.rb' + - 'ee/spec/services/ci/create_pipeline_service_spec.rb' + - 'ee/spec/services/security/security_orchestration_policies/create_pipeline_service_spec.rb' + - 'ee/spec/services/security/security_orchestration_policies/policy_commit_service_spec.rb' + - 'ee/spec/support/helpers/ee/ldap_helpers.rb' + - 'ee/spec/tasks/gitlab/elastic_rake_spec.rb' + - 'lib/api/version.rb' + - 'lib/backup/helper.rb' + - 'lib/feature/shared.rb' + - 'lib/gitlab/cache/import/caching.rb' + - 'lib/gitlab/conflict/file_collection.rb' + - 'lib/gitlab/database.rb' + - 'lib/gitlab/database/migration_helpers.rb' + - 'lib/gitlab/database/migration_helpers/v2.rb' + - 'lib/gitlab/exclusive_lease.rb' + - 'lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb' + - 'lib/gitlab/sql/set_operator.rb' + - 'lib/gitlab/utils/delegator_override/validator.rb' + - 'lib/tasks/gitlab/docs/compile_deprecations.rake' + - 'lib/tasks/gitlab/password.rake' + - 'qa/qa/scenario/test/sanity/selectors.rb' + - 'qa/qa/service/docker_run/gitlab_runner.rb' + - 'qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb' + - 'qa/qa/specs/features/browser_ui/3_create/web_ide/web_terminal_spec.rb' + - 'qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb' + - 'qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb' + - 'qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb' + - 'qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb' + - 'rubocop/cop/database/multiple_databases.rb' + - 'rubocop/cop/default_scope.rb' + - 'rubocop/cop/file_decompression.rb' + - 'rubocop/cop/gitlab/httparty.rb' + - 'rubocop/cop/gitlab/json.rb' + - 'rubocop/cop/gitlab/module_with_instance_variables.rb' + - 'rubocop/cop/gitlab/predicate_memoization.rb' + - 'spec/controllers/projects/pipelines_controller_spec.rb' + - 'spec/deprecation_toolkit_env.rb' + - 'spec/factories/packages/debian/distribution.rb' + - 'spec/factories/packages/debian/file_metadatum.rb' + - 'spec/features/projects/commit/user_comments_on_commit_spec.rb' + - 'spec/features/task_lists_spec.rb' + - 'spec/helpers/markup_helper_spec.rb' + - 'spec/initializers/100_patch_omniauth_oauth2_spec.rb' + - 'spec/initializers/rack_multipart_patch_spec.rb' + - 'spec/initializers/secret_token_spec.rb' + - 'spec/initializers/validate_database_config_spec.rb' + - 'spec/lib/banzai/filter/footnote_filter_spec.rb' + - 'spec/lib/banzai/pipeline/full_pipeline_spec.rb' + - 'spec/lib/gitlab/auth/ldap/config_spec.rb' + - 'spec/lib/gitlab/ci/config_spec.rb' + - 'spec/lib/gitlab/ci/parsers/coverage/sax_document_spec.rb' + - 'spec/lib/gitlab/ci/parsers/test/junit_spec.rb' + - 'spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb' + - 'spec/lib/gitlab/ci/templates/templates_spec.rb' + - 'spec/lib/gitlab/ci/yaml_processor_spec.rb' + - 'spec/lib/gitlab/cluster/mixins/puma_cluster_spec.rb' + - 'spec/lib/gitlab/conflict/file_collection_spec.rb' + - 'spec/lib/gitlab/diff/file_spec.rb' + - 'spec/lib/gitlab/diff/pair_selector_spec.rb' + - 'spec/lib/gitlab/diff/parser_spec.rb' + - 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb' + - 'spec/lib/gitlab/file_hook_spec.rb' + - 'spec/lib/gitlab/form_builders/gitlab_ui_form_builder_spec.rb' + - 'spec/lib/gitlab/git/diff_spec.rb' + - 'spec/lib/gitlab/git_post_receive_spec.rb' + - 'spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb' + - 'spec/lib/gitlab/import_export/attributes_permitter_spec.rb' + - 'spec/lib/gitlab/import_export/config_spec.rb' + - 'spec/lib/gitlab/kubernetes/helm/v2/delete_command_spec.rb' + - 'spec/lib/gitlab/kubernetes/helm/v2/init_command_spec.rb' + - 'spec/lib/gitlab/kubernetes/helm/v2/install_command_spec.rb' + - 'spec/lib/gitlab/kubernetes/helm/v2/patch_command_spec.rb' + - 'spec/lib/gitlab/kubernetes/helm/v2/reset_command_spec.rb' + - 'spec/lib/gitlab/kubernetes/helm/v3/delete_command_spec.rb' + - 'spec/lib/gitlab/kubernetes/helm/v3/install_command_spec.rb' + - 'spec/lib/gitlab/kubernetes/helm/v3/patch_command_spec.rb' + - 'spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb' + - 'spec/lib/gitlab/patch/database_config_spec.rb' + - 'spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb' + - 'spec/lib/gitlab/quick_actions/substitution_definition_spec.rb' + - 'spec/lib/gitlab/static_site_editor/config/file_config_spec.rb' + - 'spec/lib/gitlab/web_ide/config_spec.rb' + - 'spec/lib/gitlab/webpack/file_loader_spec.rb' + - 'spec/lib/gitlab/webpack/graphql_known_operations_spec.rb' + - 'spec/lib/gitlab/webpack/manifest_spec.rb' + - 'spec/lib/gitlab/word_diff/parser_spec.rb' + - 'spec/models/ci/bridge_spec.rb' + - 'spec/models/clusters/applications/cert_manager_spec.rb' + - 'spec/models/concerns/ci/maskable_spec.rb' + - 'spec/models/integrations/asana_spec.rb' + - 'spec/models/ssh_host_key_spec.rb' + - 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb' + - 'spec/services/ci/after_requeue_job_service_spec.rb' + - 'spec/services/ci/create_downstream_pipeline_service_spec.rb' + - 'spec/services/ci/create_pipeline_service/cache_spec.rb' + - 'spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb' + - 'spec/services/ci/create_pipeline_service/include_spec.rb' + - 'spec/services/ci/create_pipeline_service/merge_requests_spec.rb' + - 'spec/services/ci/create_pipeline_service/parallel_spec.rb' + - 'spec/services/ci/create_pipeline_service/parameter_content_spec.rb' + - 'spec/services/ci/create_pipeline_service/rules_spec.rb' + - 'spec/services/ci/create_pipeline_service_spec.rb' + - 'spec/services/ci/create_web_ide_terminal_service_spec.rb' + - 'spec/services/ci/parse_dotenv_artifact_service_spec.rb' + - 'spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb' + - 'spec/services/google_cloud/generate_pipeline_service_spec.rb' + - 'spec/services/task_list_toggle_service_spec.rb' + - 'spec/support/helpers/seed_helper.rb' + - 'spec/support/helpers/stub_object_storage.rb' + - 'spec/support/shared_examples/helm_commands_shared_examples.rb' + - 'spec/support/shared_examples/models/taskable_shared_examples.rb' + - 'spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb' + - 'spec/support/test_reports/test_reports_helper.rb' + - 'spec/workers/post_receive_spec.rb' diff --git a/app/assets/javascripts/content_editor/constants/code_block_languages.js b/app/assets/javascripts/content_editor/constants/code_block_languages.js new file mode 100644 index 00000000000..1a4dbe4fa22 --- /dev/null +++ b/app/assets/javascripts/content_editor/constants/code_block_languages.js @@ -0,0 +1,210 @@ +/* eslint-disable @gitlab/require-i18n-strings */ +// List of languages referenced from https://github.com/wooorm/lowlight#data +const CODE_BLOCK_LANGUAGES = [ + { syntax: '1c', label: '1C:Enterprise' }, + { syntax: 'abnf', label: 'Augmented Backus-Naur Form' }, + { syntax: 'accesslog', label: 'Apache Access Log' }, + { syntax: 'actionscript', variants: 'as', label: 'ActionScript' }, + { syntax: 'ada', label: 'Ada' }, + { syntax: 'angelscript', variants: 'asc', label: 'AngelScript' }, + { syntax: 'apache', variants: 'apacheconf', label: 'Apache config' }, + { syntax: 'applescript', variants: 'osascript', label: 'AppleScript' }, + { syntax: 'arcade', label: 'ArcGIS Arcade' }, + { syntax: 'arduino', variants: 'ino', label: 'Arduino' }, + { syntax: 'armasm', variants: 'arm', label: 'ARM Assembly' }, + { syntax: 'asciidoc', variants: 'adoc', label: 'AsciiDoc' }, + { syntax: 'aspectj', label: 'AspectJ' }, + { syntax: 'autohotkey', variants: 'ahk', label: 'AutoHotkey' }, + { syntax: 'autoit', label: 'AutoIt' }, + { syntax: 'avrasm', label: 'AVR Assembly' }, + { syntax: 'awk', label: 'Awk' }, + { syntax: 'axapta', variants: 'x++', label: 'X++' }, + { syntax: 'bash', variants: 'sh', label: 'Bash' }, + { syntax: 'basic', label: 'BASIC' }, + { syntax: 'bnf', label: 'Backus-Naur Form' }, + { syntax: 'brainfuck', variants: 'bf', label: 'Brainfuck' }, + { syntax: 'c', variants: 'h', label: 'C' }, + { syntax: 'cal', label: 'C/AL' }, + { syntax: 'capnproto', variants: 'capnp', label: "Cap'n Proto" }, + { syntax: 'ceylon', label: 'Ceylon' }, + { syntax: 'clean', variants: 'icl, dcl', label: 'Clean' }, + { syntax: 'clojure', variants: 'clj, edn', label: 'Clojure' }, + { syntax: 'clojure-repl', label: 'Clojure REPL' }, + { syntax: 'cmake', variants: 'cmake.in', label: 'CMake' }, + { syntax: 'coffeescript', variants: 'coffee, cson, iced', label: 'CoffeeScript' }, + { syntax: 'coq', label: 'Coq' }, + { syntax: 'cos', variants: 'cls', label: 'Caché Object Script' }, + { syntax: 'cpp', variants: 'cc, c++, h++, hpp, hh, hxx, cxx', label: 'C++' }, + { syntax: 'crmsh', variants: 'crm, pcmk', label: 'crmsh' }, + { syntax: 'crystal', variants: 'cr', label: 'Crystal' }, + { syntax: 'csharp', variants: 'cs, c#', label: 'C#' }, + { syntax: 'csp', label: 'CSP' }, + { syntax: 'css', label: 'CSS' }, + { syntax: 'd', label: 'D' }, + { syntax: 'dart', label: 'Dart' }, + { syntax: 'delphi', variants: 'dpr, dfm, pas, pascal', label: 'Delphi' }, + { syntax: 'diff', variants: 'patch', label: 'Diff' }, + { syntax: 'django', variants: 'jinja', label: 'Django' }, + { syntax: 'dns', variants: 'bind, zone', label: 'DNS Zone' }, + { syntax: 'dockerfile', variants: 'docker', label: 'Dockerfile' }, + { syntax: 'dos', variants: 'bat, cmd', label: 'Batch file (DOS)' }, + { syntax: 'dsconfig', label: 'DSConfig' }, + { syntax: 'dts', label: 'Device Tree' }, + { syntax: 'dust', variants: 'dst', label: 'Dust' }, + { syntax: 'ebnf', label: 'Extended Backus-Naur Form' }, + { syntax: 'elixir', variants: 'ex, exs', label: 'Elixir' }, + { syntax: 'elm', label: 'Elm' }, + { syntax: 'erb', label: 'ERB' }, + { syntax: 'erlang', variants: 'erl', label: 'Erlang' }, + { syntax: 'erlang-repl', label: 'Erlang REPL' }, + { syntax: 'excel', variants: 'xlsx, xls', label: 'Excel formulae' }, + { syntax: 'fix', label: 'FIX' }, + { syntax: 'flix', label: 'Flix' }, + { syntax: 'fortran', variants: 'f90, f95', label: 'Fortran' }, + { syntax: 'fsharp', variants: 'fs, f#', label: 'F#' }, + { syntax: 'gams', variants: 'gms', label: 'GAMS' }, + { syntax: 'gauss', variants: 'gss', label: 'GAUSS' }, + { syntax: 'gcode', variants: 'nc', label: 'G-code (ISO 6983)' }, + { syntax: 'gherkin', variants: 'feature', label: 'Gherkin' }, + { syntax: 'glsl', label: 'GLSL' }, + { syntax: 'gml', label: 'GML' }, + { syntax: 'go', variants: 'golang', label: 'Go' }, + { syntax: 'golo', label: 'Golo' }, + { syntax: 'gradle', label: 'Gradle' }, + { syntax: 'graphql', variants: 'gql', label: 'GraphQL' }, + { syntax: 'groovy', label: 'Groovy' }, + { syntax: 'haml', label: 'HAML' }, + { + syntax: 'handlebars', + variants: 'hbs, html.hbs, html.handlebars, htmlbars', + label: 'Handlebars', + }, + { syntax: 'haskell', variants: 'hs', label: 'Haskell' }, + { syntax: 'haxe', variants: 'hx', label: 'Haxe' }, + { syntax: 'hsp', label: 'HSP' }, + { syntax: 'http', variants: 'https', label: 'HTTP' }, + { syntax: 'hy', variants: 'hylang', label: 'Hy' }, + { syntax: 'inform7', variants: 'i7', label: 'Inform 7' }, + { syntax: 'ini', variants: 'toml', label: 'TOML, also INI' }, + { syntax: 'irpf90', label: 'IRPF90' }, + { syntax: 'isbl', label: 'ISBL' }, + { syntax: 'java', variants: 'jsp', label: 'Java' }, + { syntax: 'javascript', variants: 'js, jsx, mjs, cjs', label: 'Javascript' }, + { syntax: 'jboss-cli', variants: 'wildfly-cli', label: 'JBoss CLI' }, + { syntax: 'json', label: 'JSON' }, + { syntax: 'julia', label: 'Julia' }, + { syntax: 'julia-repl', variants: 'jldoctest', label: 'Julia REPL' }, + { syntax: 'kotlin', variants: 'kt, kts', label: 'Kotlin' }, + { syntax: 'lasso', variants: 'ls, lassoscript', label: 'Lasso' }, + { syntax: 'latex', variants: 'tex', label: 'LaTeX' }, + { syntax: 'ldif', label: 'LDIF' }, + { syntax: 'leaf', label: 'Leaf' }, + { syntax: 'less', label: 'Less' }, + { syntax: 'lisp', label: 'Lisp' }, + { syntax: 'livecodeserver', label: 'LiveCode' }, + { syntax: 'livescript', variants: 'ls', label: 'LiveScript' }, + { syntax: 'llvm', label: 'LLVM IR' }, + { syntax: 'lsl', label: 'LSL (Linden Scripting Language)' }, + { syntax: 'lua', label: 'Lua' }, + { syntax: 'makefile', variants: 'mk, mak, make', label: 'Makefile' }, + { syntax: 'markdown', variants: 'md, mkdown, mkd', label: 'Markdown' }, + { syntax: 'mathematica', variants: 'mma, wl', label: 'Mathematica' }, + { syntax: 'matlab', label: 'Matlab' }, + { syntax: 'maxima', label: 'Maxima' }, + { syntax: 'mel', label: 'MEL' }, + { syntax: 'mercury', variants: 'm, moo', label: 'Mercury' }, + { syntax: 'mipsasm', variants: 'mips', label: 'MIPS Assembly' }, + { syntax: 'mizar', label: 'Mizar' }, + { syntax: 'mojolicious', label: 'Mojolicious' }, + { syntax: 'monkey', label: 'Monkey' }, + { syntax: 'moonscript', variants: 'moon', label: 'MoonScript' }, + { syntax: 'n1ql', label: 'N1QL' }, + { syntax: 'nestedtext', variants: 'nt', label: 'Nested Text' }, + { syntax: 'nginx', variants: 'nginxconf', label: 'Nginx config' }, + { syntax: 'nim', label: 'Nim' }, + { syntax: 'nix', variants: 'nixos', label: 'Nix' }, + { syntax: 'node-repl', label: 'Node REPL' }, + { syntax: 'nsis', label: 'NSIS' }, + { + syntax: 'objectivec', + variants: 'mm, objc, obj-c, obj-c++, objective-c++', + label: 'Objective-C', + }, + { syntax: 'ocaml', variants: 'ml', label: 'OCaml' }, + { syntax: 'openscad', variants: 'scad', label: 'OpenSCAD' }, + { syntax: 'oxygene', label: 'Oxygene' }, + { syntax: 'parser3', label: 'Parser3' }, + { syntax: 'perl', variants: 'pl, pm', label: 'Perl' }, + { syntax: 'pf', variants: 'pf.conf', label: 'Packet Filter config' }, + { syntax: 'pgsql', variants: 'postgres, postgresql', label: 'PostgreSQL' }, + { syntax: 'php', label: 'PHP' }, + { syntax: 'php-template', label: 'PHP template' }, + { syntax: 'plaintext', variants: 'text, txt', label: 'Plain text' }, + { syntax: 'pony', label: 'Pony' }, + { syntax: 'powershell', variants: 'pwsh, ps, ps1', label: 'PowerShell' }, + { syntax: 'processing', variants: 'pde', label: 'Processing' }, + { syntax: 'profile', label: 'Python profiler' }, + { syntax: 'prolog', label: 'Prolog' }, + { syntax: 'properties', label: '.properties' }, + { syntax: 'protobuf', label: 'Protocol Buffers' }, + { syntax: 'puppet', variants: 'pp', label: 'Puppet' }, + { syntax: 'purebasic', variants: 'pb, pbi', label: 'PureBASIC' }, + { syntax: 'python', variants: 'py, gyp, ipython', label: 'Python' }, + { syntax: 'python-repl', variants: 'pycon', label: 'Python REPL' }, + { syntax: 'q', variants: 'k, kdb', label: 'Q' }, + { syntax: 'qml', variants: 'qt', label: 'QML' }, + { syntax: 'r', label: 'R' }, + { syntax: 'reasonml', variants: 're', label: 'ReasonML' }, + { syntax: 'rib', label: 'RenderMan RIB' }, + { syntax: 'roboconf', variants: 'graph, instances', label: 'Roboconf' }, + { syntax: 'routeros', variants: 'mikrotik', label: 'Microtik RouterOS script' }, + { syntax: 'rsl', label: 'RenderMan RSL' }, + { syntax: 'ruby', variants: 'rb, gemspec, podspec, thor, irb', label: 'Ruby' }, + { syntax: 'ruleslanguage', label: 'Oracle Rules Language' }, + { syntax: 'rust', variants: 'rs', label: 'Rust' }, + { syntax: 'sas', label: 'SAS' }, + { syntax: 'scala', label: 'Scala' }, + { syntax: 'scheme', label: 'Scheme' }, + { syntax: 'scilab', variants: 'sci', label: 'Scilab' }, + { syntax: 'scss', label: 'SCSS' }, + { syntax: 'shell', variants: 'console, shellsession', label: 'Shell Session' }, + { syntax: 'smali', label: 'Smali' }, + { syntax: 'smalltalk', variants: 'st', label: 'Smalltalk' }, + { syntax: 'sml', variants: 'ml', label: 'SML (Standard ML)' }, + { syntax: 'sqf', label: 'SQF' }, + { syntax: 'sql', label: 'SQL' }, + { syntax: 'stan', variants: 'stanfuncs', label: 'Stan' }, + { syntax: 'stata', variants: 'do, ado', label: 'Stata' }, + { syntax: 'step21', variants: 'p21, step, stp', label: 'STEP Part 21' }, + { syntax: 'stylus', variants: 'styl', label: 'Stylus' }, + { syntax: 'subunit', label: 'SubUnit' }, + { syntax: 'swift', label: 'Swift' }, + { syntax: 'taggerscript', label: 'Tagger Script' }, + { syntax: 'tap', label: 'Test Anything Protocol' }, + { syntax: 'tcl', variants: 'tk', label: 'Tcl' }, + { syntax: 'thrift', label: 'Thrift' }, + { syntax: 'tp', label: 'TP' }, + { syntax: 'twig', variants: 'craftcms', label: 'Twig' }, + { syntax: 'typescript', variants: 'ts, tsx', label: 'TypeScript' }, + { syntax: 'vala', label: 'Vala' }, + { syntax: 'vbnet', variants: 'vb', label: 'Visual Basic .NET' }, + { syntax: 'vbscript', variants: 'vbs', label: 'VBScript' }, + { syntax: 'vbscript-html', label: 'VBScript in HTML' }, + { syntax: 'verilog', variants: 'v, sv, svh', label: 'Verilog' }, + { syntax: 'vhdl', label: 'VHDL' }, + { syntax: 'vim', label: 'Vim Script' }, + { syntax: 'wasm', label: 'WebAssembly' }, + { syntax: 'wren', label: 'Wren' }, + { syntax: 'x86asm', label: 'Intel x86 Assembly' }, + { syntax: 'xl', variants: 'tao', label: 'XL' }, + { + syntax: 'xml', + variants: 'html, xhtml, rss, atom, xjb, xsd, xsl, plist, wsf, svg', + label: 'HTML, XML', + }, + { syntax: 'xquery', variants: 'xpath, xq', label: 'XQuery' }, + { syntax: 'yaml', variants: 'yml', label: 'YAML' }, + { syntax: 'zephir', variants: 'zep', label: 'Zephir' }, +]; + +export default CODE_BLOCK_LANGUAGES; diff --git a/app/assets/javascripts/content_editor/constants.js b/app/assets/javascripts/content_editor/constants/index.js index a39a243ec6b..a39a243ec6b 100644 --- a/app/assets/javascripts/content_editor/constants.js +++ b/app/assets/javascripts/content_editor/constants/index.js diff --git a/app/assets/javascripts/content_editor/services/code_block_language_loader.js b/app/assets/javascripts/content_editor/services/code_block_language_loader.js index 081400cfd9a..c967dd899de 100644 --- a/app/assets/javascripts/content_editor/services/code_block_language_loader.js +++ b/app/assets/javascripts/content_editor/services/code_block_language_loader.js @@ -1,215 +1,6 @@ import { lowlight } from 'lowlight/lib/core'; import { __, sprintf } from '~/locale'; - -/* eslint-disable @gitlab/require-i18n-strings */ -// List of languages referenced from https://github.com/wooorm/lowlight#data -const CODE_BLOCK_LANGUAGES = [ - { syntax: '1c', label: '1C:Enterprise' }, - { syntax: 'abnf', label: 'Augmented Backus-Naur Form' }, - { syntax: 'accesslog', label: 'Apache Access Log' }, - { syntax: 'actionscript', variants: 'as', label: 'ActionScript' }, - { syntax: 'ada', label: 'Ada' }, - { syntax: 'angelscript', variants: 'asc', label: 'AngelScript' }, - { syntax: 'apache', variants: 'apacheconf', label: 'Apache config' }, - { syntax: 'applescript', variants: 'osascript', label: 'AppleScript' }, - { syntax: 'arcade', label: 'ArcGIS Arcade' }, - { syntax: 'arduino', variants: 'ino', label: 'Arduino' }, - { syntax: 'armasm', variants: 'arm', label: 'ARM Assembly' }, - { syntax: 'asciidoc', variants: 'adoc', label: 'AsciiDoc' }, - { syntax: 'aspectj', label: 'AspectJ' }, - { syntax: 'autohotkey', variants: 'ahk', label: 'AutoHotkey' }, - { syntax: 'autoit', label: 'AutoIt' }, - { syntax: 'avrasm', label: 'AVR Assembly' }, - { syntax: 'awk', label: 'Awk' }, - { syntax: 'axapta', variants: 'x++', label: 'X++' }, - { syntax: 'bash', variants: 'sh', label: 'Bash' }, - { syntax: 'basic', label: 'BASIC' }, - { syntax: 'bnf', label: 'Backus-Naur Form' }, - { syntax: 'brainfuck', variants: 'bf', label: 'Brainfuck' }, - { syntax: 'c', variants: 'h', label: 'C' }, - { syntax: 'cal', label: 'C/AL' }, - { syntax: 'capnproto', variants: 'capnp', label: "Cap'n Proto" }, - { syntax: 'ceylon', label: 'Ceylon' }, - { syntax: 'clean', variants: 'icl, dcl', label: 'Clean' }, - { syntax: 'clojure', variants: 'clj, edn', label: 'Clojure' }, - { syntax: 'clojure-repl', label: 'Clojure REPL' }, - { syntax: 'cmake', variants: 'cmake.in', label: 'CMake' }, - { syntax: 'coffeescript', variants: 'coffee, cson, iced', label: 'CoffeeScript' }, - { syntax: 'coq', label: 'Coq' }, - { syntax: 'cos', variants: 'cls', label: 'Caché Object Script' }, - { syntax: 'cpp', variants: 'cc, c++, h++, hpp, hh, hxx, cxx', label: 'C++' }, - { syntax: 'crmsh', variants: 'crm, pcmk', label: 'crmsh' }, - { syntax: 'crystal', variants: 'cr', label: 'Crystal' }, - { syntax: 'csharp', variants: 'cs, c#', label: 'C#' }, - { syntax: 'csp', label: 'CSP' }, - { syntax: 'css', label: 'CSS' }, - { syntax: 'd', label: 'D' }, - { syntax: 'dart', label: 'Dart' }, - { syntax: 'delphi', variants: 'dpr, dfm, pas, pascal', label: 'Delphi' }, - { syntax: 'diff', variants: 'patch', label: 'Diff' }, - { syntax: 'django', variants: 'jinja', label: 'Django' }, - { syntax: 'dns', variants: 'bind, zone', label: 'DNS Zone' }, - { syntax: 'dockerfile', variants: 'docker', label: 'Dockerfile' }, - { syntax: 'dos', variants: 'bat, cmd', label: 'Batch file (DOS)' }, - { syntax: 'dsconfig', label: 'DSConfig' }, - { syntax: 'dts', label: 'Device Tree' }, - { syntax: 'dust', variants: 'dst', label: 'Dust' }, - { syntax: 'ebnf', label: 'Extended Backus-Naur Form' }, - { syntax: 'elixir', variants: 'ex, exs', label: 'Elixir' }, - { syntax: 'elm', label: 'Elm' }, - { syntax: 'erb', label: 'ERB' }, - { syntax: 'erlang', variants: 'erl', label: 'Erlang' }, - { syntax: 'erlang-repl', label: 'Erlang REPL' }, - { syntax: 'excel', variants: 'xlsx, xls', label: 'Excel formulae' }, - { syntax: 'fix', label: 'FIX' }, - { syntax: 'flix', label: 'Flix' }, - { syntax: 'fortran', variants: 'f90, f95', label: 'Fortran' }, - { syntax: 'fsharp', variants: 'fs, f#', label: 'F#' }, - { syntax: 'gams', variants: 'gms', label: 'GAMS' }, - { syntax: 'gauss', variants: 'gss', label: 'GAUSS' }, - { syntax: 'gcode', variants: 'nc', label: 'G-code (ISO 6983)' }, - { syntax: 'gherkin', variants: 'feature', label: 'Gherkin' }, - { syntax: 'glsl', label: 'GLSL' }, - { syntax: 'gml', label: 'GML' }, - { syntax: 'go', variants: 'golang', label: 'Go' }, - { syntax: 'golo', label: 'Golo' }, - { syntax: 'gradle', label: 'Gradle' }, - { syntax: 'graphql', variants: 'gql', label: 'GraphQL' }, - { syntax: 'groovy', label: 'Groovy' }, - { syntax: 'haml', label: 'HAML' }, - { - syntax: 'handlebars', - variants: 'hbs, html.hbs, html.handlebars, htmlbars', - label: 'Handlebars', - }, - { syntax: 'haskell', variants: 'hs', label: 'Haskell' }, - { syntax: 'haxe', variants: 'hx', label: 'Haxe' }, - { syntax: 'hsp', label: 'HSP' }, - { syntax: 'http', variants: 'https', label: 'HTTP' }, - { syntax: 'hy', variants: 'hylang', label: 'Hy' }, - { syntax: 'inform7', variants: 'i7', label: 'Inform 7' }, - { syntax: 'ini', variants: 'toml', label: 'TOML, also INI' }, - { syntax: 'irpf90', label: 'IRPF90' }, - { syntax: 'isbl', label: 'ISBL' }, - { syntax: 'java', variants: 'jsp', label: 'Java' }, - { syntax: 'javascript', variants: 'js, jsx, mjs, cjs', label: 'Javascript' }, - { syntax: 'jboss-cli', variants: 'wildfly-cli', label: 'JBoss CLI' }, - { syntax: 'json', label: 'JSON' }, - { syntax: 'julia', label: 'Julia' }, - { syntax: 'julia-repl', variants: 'jldoctest', label: 'Julia REPL' }, - { syntax: 'kotlin', variants: 'kt, kts', label: 'Kotlin' }, - { syntax: 'lasso', variants: 'ls, lassoscript', label: 'Lasso' }, - { syntax: 'latex', variants: 'tex', label: 'LaTeX' }, - { syntax: 'ldif', label: 'LDIF' }, - { syntax: 'leaf', label: 'Leaf' }, - { syntax: 'less', label: 'Less' }, - { syntax: 'lisp', label: 'Lisp' }, - { syntax: 'livecodeserver', label: 'LiveCode' }, - { syntax: 'livescript', variants: 'ls', label: 'LiveScript' }, - { syntax: 'llvm', label: 'LLVM IR' }, - { syntax: 'lsl', label: 'LSL (Linden Scripting Language)' }, - { syntax: 'lua', label: 'Lua' }, - { syntax: 'makefile', variants: 'mk, mak, make', label: 'Makefile' }, - { syntax: 'markdown', variants: 'md, mkdown, mkd', label: 'Markdown' }, - { syntax: 'mathematica', variants: 'mma, wl', label: 'Mathematica' }, - { syntax: 'matlab', label: 'Matlab' }, - { syntax: 'maxima', label: 'Maxima' }, - { syntax: 'mel', label: 'MEL' }, - { syntax: 'mercury', variants: 'm, moo', label: 'Mercury' }, - { syntax: 'mipsasm', variants: 'mips', label: 'MIPS Assembly' }, - { syntax: 'mizar', label: 'Mizar' }, - { syntax: 'mojolicious', label: 'Mojolicious' }, - { syntax: 'monkey', label: 'Monkey' }, - { syntax: 'moonscript', variants: 'moon', label: 'MoonScript' }, - { syntax: 'n1ql', label: 'N1QL' }, - { syntax: 'nestedtext', variants: 'nt', label: 'Nested Text' }, - { syntax: 'nginx', variants: 'nginxconf', label: 'Nginx config' }, - { syntax: 'nim', label: 'Nim' }, - { syntax: 'nix', variants: 'nixos', label: 'Nix' }, - { syntax: 'node-repl', label: 'Node REPL' }, - { syntax: 'nsis', label: 'NSIS' }, - { - syntax: 'objectivec', - variants: 'mm, objc, obj-c, obj-c++, objective-c++', - label: 'Objective-C', - }, - { syntax: 'ocaml', variants: 'ml', label: 'OCaml' }, - { syntax: 'openscad', variants: 'scad', label: 'OpenSCAD' }, - { syntax: 'oxygene', label: 'Oxygene' }, - { syntax: 'parser3', label: 'Parser3' }, - { syntax: 'perl', variants: 'pl, pm', label: 'Perl' }, - { syntax: 'pf', variants: 'pf.conf', label: 'Packet Filter config' }, - { syntax: 'pgsql', variants: 'postgres, postgresql', label: 'PostgreSQL' }, - { syntax: 'php', label: 'PHP' }, - { syntax: 'php-template', label: 'PHP template' }, - { syntax: 'plaintext', variants: 'text, txt', label: 'Plain text' }, - { syntax: 'pony', label: 'Pony' }, - { syntax: 'powershell', variants: 'pwsh, ps, ps1', label: 'PowerShell' }, - { syntax: 'processing', variants: 'pde', label: 'Processing' }, - { syntax: 'profile', label: 'Python profiler' }, - { syntax: 'prolog', label: 'Prolog' }, - { syntax: 'properties', label: '.properties' }, - { syntax: 'protobuf', label: 'Protocol Buffers' }, - { syntax: 'puppet', variants: 'pp', label: 'Puppet' }, - { syntax: 'purebasic', variants: 'pb, pbi', label: 'PureBASIC' }, - { syntax: 'python', variants: 'py, gyp, ipython', label: 'Python' }, - { syntax: 'python-repl', variants: 'pycon', label: 'Python REPL' }, - { syntax: 'q', variants: 'k, kdb', label: 'Q' }, - { syntax: 'qml', variants: 'qt', label: 'QML' }, - { syntax: 'r', label: 'R' }, - { syntax: 'reasonml', variants: 're', label: 'ReasonML' }, - { syntax: 'rib', label: 'RenderMan RIB' }, - { syntax: 'roboconf', variants: 'graph, instances', label: 'Roboconf' }, - { syntax: 'routeros', variants: 'mikrotik', label: 'Microtik RouterOS script' }, - { syntax: 'rsl', label: 'RenderMan RSL' }, - { syntax: 'ruby', variants: 'rb, gemspec, podspec, thor, irb', label: 'Ruby' }, - { syntax: 'ruleslanguage', label: 'Oracle Rules Language' }, - { syntax: 'rust', variants: 'rs', label: 'Rust' }, - { syntax: 'sas', label: 'SAS' }, - { syntax: 'scala', label: 'Scala' }, - { syntax: 'scheme', label: 'Scheme' }, - { syntax: 'scilab', variants: 'sci', label: 'Scilab' }, - { syntax: 'scss', label: 'SCSS' }, - { syntax: 'shell', variants: 'console, shellsession', label: 'Shell Session' }, - { syntax: 'smali', label: 'Smali' }, - { syntax: 'smalltalk', variants: 'st', label: 'Smalltalk' }, - { syntax: 'sml', variants: 'ml', label: 'SML (Standard ML)' }, - { syntax: 'sqf', label: 'SQF' }, - { syntax: 'sql', label: 'SQL' }, - { syntax: 'stan', variants: 'stanfuncs', label: 'Stan' }, - { syntax: 'stata', variants: 'do, ado', label: 'Stata' }, - { syntax: 'step21', variants: 'p21, step, stp', label: 'STEP Part 21' }, - { syntax: 'stylus', variants: 'styl', label: 'Stylus' }, - { syntax: 'subunit', label: 'SubUnit' }, - { syntax: 'swift', label: 'Swift' }, - { syntax: 'taggerscript', label: 'Tagger Script' }, - { syntax: 'tap', label: 'Test Anything Protocol' }, - { syntax: 'tcl', variants: 'tk', label: 'Tcl' }, - { syntax: 'thrift', label: 'Thrift' }, - { syntax: 'tp', label: 'TP' }, - { syntax: 'twig', variants: 'craftcms', label: 'Twig' }, - { syntax: 'typescript', variants: 'ts, tsx', label: 'TypeScript' }, - { syntax: 'vala', label: 'Vala' }, - { syntax: 'vbnet', variants: 'vb', label: 'Visual Basic .NET' }, - { syntax: 'vbscript', variants: 'vbs', label: 'VBScript' }, - { syntax: 'vbscript-html', label: 'VBScript in HTML' }, - { syntax: 'verilog', variants: 'v, sv, svh', label: 'Verilog' }, - { syntax: 'vhdl', label: 'VHDL' }, - { syntax: 'vim', label: 'Vim Script' }, - { syntax: 'wasm', label: 'WebAssembly' }, - { syntax: 'wren', label: 'Wren' }, - { syntax: 'x86asm', label: 'Intel x86 Assembly' }, - { syntax: 'xl', variants: 'tao', label: 'XL' }, - { - syntax: 'xml', - variants: 'html, xhtml, rss, atom, xjb, xsd, xsl, plist, wsf, svg', - label: 'HTML, XML', - }, - { syntax: 'xquery', variants: 'xpath, xq', label: 'XQuery' }, - { syntax: 'yaml', variants: 'yml', label: 'YAML' }, - { syntax: 'zephir', variants: 'zep', label: 'Zephir' }, -]; -/* eslint-enable @gitlab/require-i18n-strings */ +import CODE_BLOCK_LANGUAGES from '../constants/code_block_languages'; const codeBlockLanguageLoader = { lowlight, diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue index 4c7b8e8f667..cd726818031 100644 --- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue +++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue @@ -1,42 +1,33 @@ <script> -import { GlIcon } from '@gitlab/ui'; -import { mapState, mapActions } from 'vuex'; +import { GlTooltipDirective, GlSafeHtmlDirective, GlIcon, GlLoadingIcon } from '@gitlab/ui'; +import { mapActions } from 'vuex'; import createFlash from '~/flash'; import { s__, sprintf } from '~/locale'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; -import { UNFOLD_COUNT, INLINE_DIFF_VIEW_TYPE, INLINE_DIFF_LINES_KEY } from '../constants'; +import { UNFOLD_COUNT, INLINE_DIFF_LINES_KEY } from '../constants'; import * as utils from '../store/utils'; const EXPAND_ALL = 0; const EXPAND_UP = 1; const EXPAND_DOWN = 2; -const lineNumberByViewType = (viewType, diffLine) => { - const numberGetters = { - [INLINE_DIFF_VIEW_TYPE]: (line) => line?.new_line, - }; - const numberGetter = numberGetters[viewType]; - return numberGetter && numberGetter(diffLine); -}; - -const i18n = { - showMore: sprintf(s__('Diffs|Show %{unfoldCount} lines'), { unfoldCount: UNFOLD_COUNT }), - showAll: s__('Diffs|Show all unchanged lines'), -}; - export default { - i18n, + i18n: { + showMore: sprintf(s__('Diffs|Show %{unfoldCount} lines'), { unfoldCount: UNFOLD_COUNT }), + showAll: s__('Diffs|Show all unchanged lines'), + }, components: { GlIcon, + GlLoadingIcon, + }, + directives: { + GlTooltip: GlTooltipDirective, + SafeHtml: GlSafeHtmlDirective, }, mixins: [glFeatureFlagsMixin()], props: { - fileHash: { - type: String, - required: true, - }, - contextLinesPath: { - type: String, + file: { + type: Object, required: true, }, line: { @@ -53,34 +44,45 @@ export default { required: false, default: false, }, + inline: { + type: Boolean, + required: true, + }, + lineCountBetween: { + type: Number, + required: false, + default: -1, + }, + }, + data() { + return { loading: { up: false, down: false, all: false } }; }, computed: { - ...mapState({ - diffFiles: (state) => state.diffs.diffFiles, - }), canExpandUp() { return !this.isBottom; }, canExpandDown() { return this.isBottom || !this.isTop; }, - }, - created() { - this.EXPAND_DOWN = EXPAND_DOWN; - this.EXPAND_UP = EXPAND_UP; + isLineCountSmall() { + return this.lineCountBetween >= 20 || this.lineCountBetween === -1; + }, + showExpandDown() { + return this.canExpandDown && this.isLineCountSmall; + }, + showExpandUp() { + return this.canExpandUp && this.isLineCountSmall; + }, }, methods: { ...mapActions('diffs', ['loadMoreLines']), getPrevLineNumber(oldLineNumber, newLineNumber) { - const diffFile = utils.findDiffFile(this.diffFiles, this.fileHash); - const index = utils.getPreviousLineIndex(INLINE_DIFF_VIEW_TYPE, diffFile, { + const index = utils.getPreviousLineIndex(this.file, { oldLineNumber, newLineNumber, }); - return ( - lineNumberByViewType(INLINE_DIFF_VIEW_TYPE, diffFile[INLINE_DIFF_LINES_KEY][index - 2]) || 0 - ); + return this.file[INLINE_DIFF_LINES_KEY][index - 2]?.new_line || 0; }, callLoadMoreLines( endpoint, @@ -99,6 +101,9 @@ export default { message: s__('Diffs|Something went wrong while fetching diff lines.'), }); this.isRequesting = false; + }) + .finally(() => { + this.loading = { up: false, down: false, all: false }; }); }, handleExpandLines(type = EXPAND_ALL) { @@ -107,25 +112,26 @@ export default { } this.isRequesting = true; - const endpoint = this.contextLinesPath; - const { fileHash } = this; - const view = INLINE_DIFF_VIEW_TYPE; + const endpoint = this.file.context_lines_path; const oldLineNumber = this.line.meta_data.old_pos || 0; const newLineNumber = this.line.meta_data.new_pos || 0; const offset = newLineNumber - oldLineNumber; - const expandOptions = { endpoint, fileHash, view, oldLineNumber, newLineNumber, offset }; + const expandOptions = { endpoint, oldLineNumber, newLineNumber, offset }; if (type === EXPAND_UP) { + this.loading.up = true; this.handleExpandUpLines(expandOptions); } else if (type === EXPAND_DOWN) { + this.loading.down = true; this.handleExpandDownLines(expandOptions); } else { + this.loading.all = true; this.handleExpandAllLines(expandOptions); } }, handleExpandUpLines(expandOptions) { - const { endpoint, fileHash, view, oldLineNumber, newLineNumber, offset } = expandOptions; + const { endpoint, oldLineNumber, newLineNumber, offset } = expandOptions; const bottom = this.isBottom; const lineNumber = newLineNumber - 1; @@ -139,15 +145,13 @@ export default { unfold = false; } - const params = { since, to, bottom, offset, unfold, view }; + const params = { since, to, bottom, offset, unfold }; const lineNumbers = { oldLineNumber, newLineNumber }; - this.callLoadMoreLines(endpoint, params, lineNumbers, fileHash); + this.callLoadMoreLines(endpoint, params, lineNumbers, this.file.file_hash); }, handleExpandDownLines(expandOptions) { const { endpoint, - fileHash, - view, oldLineNumber: metaOldPos, newLineNumber: metaNewPos, offset, @@ -183,19 +187,19 @@ export default { } } - const params = { since, to, bottom, offset, unfold, view }; + const params = { since, to, bottom, offset, unfold }; const lineNumbers = { oldLineNumber, newLineNumber }; this.callLoadMoreLines( endpoint, params, lineNumbers, - fileHash, + this.file.file_hash, isExpandDown, nextLineNumbers, ); }, handleExpandAllLines(expandOptions) { - const { endpoint, fileHash, view, oldLineNumber, newLineNumber, offset } = expandOptions; + const { endpoint, oldLineNumber, newLineNumber, offset } = expandOptions; const bottom = this.isBottom; const unfold = false; let since; @@ -213,21 +217,71 @@ export default { to = newLineNumber - 1; } - const params = { since, to, bottom, offset, unfold, view }; + const params = { since, to, bottom, offset, unfold }; const lineNumbers = { oldLineNumber, newLineNumber }; - this.callLoadMoreLines(endpoint, params, lineNumbers, fileHash); + this.callLoadMoreLines(endpoint, params, lineNumbers, this.file.file_hash); }, }, + EXPAND_DOWN, + EXPAND_UP, }; </script> <template> - <div class="content js-line-expansion-content"> + <div + v-if="glFeatures.updatedDiffExpansionButtons" + class="diff-grid-row diff-grid-row-full diff-tr line_holder match expansion" + > + <div :class="{ parallel: !inline }" class="diff-grid-left diff-grid-2-col left-side"> + <div + class="diff-td diff-line-num gl-text-center! gl-p-0! gl-w-full! gl-display-flex gl-flex-direction-column" + > + <button + v-if="showExpandDown" + v-gl-tooltip + :title="s__('Diffs|Next 20 lines')" + type="button" + class="js-unfold-down gl-rounded-0 gl-border-0 diff-line-expand-button" + @click="handleExpandLines($options.EXPAND_DOWN)" + > + <gl-loading-icon v-if="loading.down" size="sm" color="dark" inline /> + <gl-icon v-else name="expand-down" /> + </button> + <button + v-if="lineCountBetween !== -1 && lineCountBetween < 20" + v-gl-tooltip + :title="s__('Diffs|Expand all lines')" + type="button" + class="js-unfold-all gl-rounded-0 gl-border-0 diff-line-expand-button" + @click="handleExpandLines()" + > + <gl-loading-icon v-if="loading.all" size="sm" color="dark" inline /> + <gl-icon v-else name="expand" /> + </button> + <button + v-if="showExpandUp" + v-gl-tooltip + :title="s__('Diffs|Previous 20 lines')" + type="button" + class="js-unfold gl-rounded-0 gl-border-0 diff-line-expand-button" + @click="handleExpandLines($options.EXPAND_UP)" + > + <gl-loading-icon v-if="loading.up" size="sm" color="dark" inline /> + <gl-icon v-else name="expand-up" /> + </button> + </div> + <div + v-safe-html="line.rich_text" + class="gl-display-flex! gl-flex-direction-column gl-justify-content-center diff-td line_content left-side gl-white-space-normal!" + ></div> + </div> + </div> + <div v-else class="content js-line-expansion-content"> <button type="button" :disabled="!canExpandDown" class="js-unfold-down gl-mx-2 gl-py-4 gl-cursor-pointer" - @click="handleExpandLines(EXPAND_DOWN)" + @click="handleExpandLines($options.EXPAND_DOWN)" > <gl-icon :size="12" name="expand-down" /> <span>{{ $options.i18n.showMore }}</span> @@ -244,7 +298,7 @@ export default { type="button" :disabled="!canExpandUp" class="js-unfold gl-mx-2 gl-py-4 gl-cursor-pointer" - @click="handleExpandLines(EXPAND_UP)" + @click="handleExpandLines($options.EXPAND_UP)" > <gl-icon :size="12" name="expand-up" /> <span>{{ $options.i18n.showMore }}</span> diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue index 4893803a3b6..1b07b00d725 100644 --- a/app/assets/javascripts/diffs/components/diff_row.vue +++ b/app/assets/javascripts/diffs/components/diff_row.vue @@ -160,7 +160,13 @@ export default { <!-- eslint-disable-next-line vue/no-deprecated-functional-template --> <template functional> - <div :class="$options.classNameMap(props)" class="diff-grid-row diff-tr line_holder"> + <div + :class="[ + $options.classNameMap(props), + { expansion: props.line.left && props.line.left.type === 'expanded' }, + ]" + class="diff-grid-row diff-tr line_holder" + > <div :id="props.line.left && props.line.left.line_code" data-testid="left-side" diff --git a/app/assets/javascripts/diffs/components/diff_row_utils.js b/app/assets/javascripts/diffs/components/diff_row_utils.js index 99999445c43..f610ac979ca 100644 --- a/app/assets/javascripts/diffs/components/diff_row_utils.js +++ b/app/assets/javascripts/diffs/components/diff_row_utils.js @@ -10,6 +10,7 @@ import { CONFLICT_MARKER_THEIR, CONFLICT_THEIR, CONFLICT_OUR, + EXPANDED_LINE_TYPE, } from '../constants'; export const isHighlighted = (highlightedRow, line, isCommented) => { @@ -118,10 +119,12 @@ export const mapParallel = (content) => (line) => { if (right) { right = { ...right, - renderDiscussion: Boolean(hasExpandedDiscussionOnRight && right.type), + renderDiscussion: Boolean( + hasExpandedDiscussionOnRight && right.type && right.type !== EXPANDED_LINE_TYPE, + ), hasDraft: content.hasParallelDraftRight(content.diffFile.file_hash, line), lineDraft: content.draftForLine(content.diffFile.file_hash, line, 'right'), - hasCommentForm: Boolean(right.hasForm && right.type), + hasCommentForm: Boolean(right.hasForm && right.type && right.type !== EXPANDED_LINE_TYPE), emptyCellClassMap: { conflict_their: line.left?.type === CONFLICT_OUR }, addCommentTooltip: addCommentTooltip(line.right), }; diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue index f46b0a538f1..529f8e0a2f9 100644 --- a/app/assets/javascripts/diffs/components/diff_view.vue +++ b/app/assets/javascripts/diffs/components/diff_view.vue @@ -141,6 +141,18 @@ export default { table.classList.add(`${lineClass}-selected`); } }, + getCountBetweenIndex(index) { + if (index === 0) { + return -1; + } else if (!this.diffLines[index + 1]) { + return -1; + } + + return ( + Number(this.diffLines[index + 1].left.new_line) - + Number(this.diffLines[index - 1].left.new_line) + ); + }, }, userColorScheme: window.gon.user_color_scheme, }; @@ -158,38 +170,51 @@ export default { > <template v-for="(line, index) in diffLines"> <template v-if="line.isMatchLineLeft || line.isMatchLineRight"> - <div :key="`expand-${index}`" class="diff-tr line_expansion match"> - <div class="diff-td text-center gl-font-regular"> - <diff-expansion-cell - :file-hash="diffFile.file_hash" - :context-lines-path="diffFile.context_lines_path" - :line="line.left" - :is-top="index === 0" - :is-bottom="index + 1 === diffLinesLength" - /> + <diff-expansion-cell + v-if="glFeatures.updatedDiffExpansionButtons" + :key="`expand-${index}`" + :file="diffFile" + :line="line.left" + :is-top="index === 0" + :is-bottom="index + 1 === diffLinesLength" + :inline="inline" + :line-count-between="getCountBetweenIndex(index)" + /> + <template v-else> + <div :key="`expand-${index}`" class="diff-tr line_expansion old-line_expansion match"> + <div class="diff-td text-center gl-font-regular"> + <diff-expansion-cell + :file="diffFile" + :context-lines-path="diffFile.context_lines_path" + :line="line.left" + :is-top="index === 0" + :is-bottom="index + 1 === diffLinesLength" + :inline="inline" + /> + </div> </div> - </div> - <div - v-if="line.left.rich_text" - :key="`expand-definition-${index}`" - class="diff-grid-row diff-tr line_holder match" - > - <div class="diff-grid-left diff-grid-3-col left-side"> - <div class="diff-td diff-line-num"></div> - <div v-if="inline" class="diff-td diff-line-num"></div> - <div - v-safe-html="line.left.rich_text" - class="diff-td line_content left-side gl-white-space-normal!" - ></div> + <div + v-if="line.left.rich_text" + :key="`expand-definition-${index}`" + class="diff-grid-row diff-tr line_holder match" + > + <div class="diff-grid-left diff-grid-3-col left-side"> + <div class="diff-td diff-line-num"></div> + <div v-if="inline" class="diff-td diff-line-num"></div> + <div + v-safe-html="line.left.rich_text" + class="diff-td line_content left-side gl-white-space-normal!" + ></div> + </div> + <div v-if="!inline" class="diff-grid-right diff-grid-3-col right-side"> + <div class="diff-td diff-line-num"></div> + <div + v-safe-html="line.left.rich_text" + class="diff-td line_content right-side gl-white-space-normal!" + ></div> + </div> </div> - <div v-if="!inline" class="diff-grid-right diff-grid-3-col right-side"> - <div class="diff-td diff-line-num"></div> - <div - v-safe-html="line.left.rich_text" - class="diff-td line_content right-side gl-white-space-normal!" - ></div> - </div> - </div> + </template> </template> <diff-row v-if="!line.isMatchLineLeft && !line.isMatchLineRight" diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js index bbe27c0dbd6..f4b6bd85b84 100644 --- a/app/assets/javascripts/diffs/constants.js +++ b/app/assets/javascripts/diffs/constants.js @@ -1,6 +1,7 @@ export const INLINE_DIFF_VIEW_TYPE = 'inline'; export const PARALLEL_DIFF_VIEW_TYPE = 'parallel'; export const MATCH_LINE_TYPE = 'match'; +export const EXPANDED_LINE_TYPE = 'expanded'; export const OLD_NO_NEW_LINE_TYPE = 'old-nonewline'; export const NEW_NO_NEW_LINE_TYPE = 'new-nonewline'; export const CONTEXT_LINE_TYPE = 'context'; diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js index fb35114c0a9..d2b798245fc 100644 --- a/app/assets/javascripts/diffs/store/mutations.js +++ b/app/assets/javascripts/diffs/store/mutations.js @@ -4,6 +4,7 @@ import { DIFF_FILE_MANUAL_COLLAPSE, DIFF_FILE_AUTOMATIC_COLLAPSE, INLINE_DIFF_LINES_KEY, + EXPANDED_LINE_TYPE, } from '../constants'; import * as types from './mutation_types'; import { @@ -131,6 +132,7 @@ export default { : line.line_code || `${fileHash}_${line.old_line}_${line.new_line}`; return { ...line, + type: line.type || EXPANDED_LINE_TYPE, line_code: lineCode, discussions: line.discussions || [], hasForm: false, diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js index 4526a34a2bd..5656416cf2b 100644 --- a/app/assets/javascripts/diffs/store/utils.js +++ b/app/assets/javascripts/diffs/store/utils.js @@ -15,13 +15,15 @@ import { CONFLICT_MARKER, CONFLICT_MARKER_OUR, CONFLICT_MARKER_THEIR, + EXPANDED_LINE_TYPE, } from '../constants'; import { prepareRawDiffFile } from '../utils/diff_file'; export const isAdded = (line) => ['new', 'new-nonewline'].includes(line.type); export const isRemoved = (line) => ['old', 'old-nonewline'].includes(line.type); export const isUnchanged = (line) => !line.type; -export const isMeta = (line) => ['match', 'new-nonewline', 'old-nonewline'].includes(line.type); +export const isMeta = (line) => + ['match', EXPANDED_LINE_TYPE, 'new-nonewline', 'old-nonewline'].includes(line.type); export const isConflictMarker = (line) => [CONFLICT_MARKER_OUR, CONFLICT_MARKER_THEIR].includes(line.type); export const isConflictSeperator = (line) => line.type === CONFLICT_MARKER; @@ -205,7 +207,7 @@ export const findIndexInInlineLines = (lines, lineNumbers) => { ); }; -export const getPreviousLineIndex = (diffViewType, file, lineNumbers) => { +export const getPreviousLineIndex = (file, lineNumbers) => { return findIndexInInlineLines(file[INLINE_DIFF_LINES_KEY], lineNumbers); }; diff --git a/app/assets/stylesheets/framework/broadcast_messages.scss b/app/assets/stylesheets/framework/broadcast_messages.scss index 58f986ec0ae..90a7e2c2da7 100644 --- a/app/assets/stylesheets/framework/broadcast_messages.scss +++ b/app/assets/stylesheets/framework/broadcast_messages.scss @@ -19,6 +19,11 @@ p { margin-bottom: 0; } + + a { + color: inherit; + text-decoration: underline; + } } .broadcast-notification-message { diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss index f0495fdc94e..6c14eeafc0b 100644 --- a/app/assets/stylesheets/framework/diffs.scss +++ b/app/assets/stylesheets/framework/diffs.scss @@ -582,25 +582,6 @@ table.code { } } -.diff-expansion-cell { - flex: 1 1; - min-width: max-content; -} - -.diff-expansion-cell-middle { - flex: 0 1 max-content; -} - -@media only screen and (min-width: $breakpoint-xl) { - .diff-expansion-cell-start { - text-align: right; - } - - .diff-expansion-cell-end { - text-align: left; - } -} - // Merge request diff grid layout .diff-grid { .diff-td { @@ -612,6 +593,10 @@ table.code { .diff-grid-row { display: grid; grid-template-columns: 1fr 1fr; + + &.diff-grid-row-full { + grid-template-columns: 1fr; + } } .diff-grid-left, @@ -626,6 +611,14 @@ table.code { grid-template-columns: 50px 1fr !important; } + .diff-grid-2-col { + grid-template-columns: 100px 1fr !important; + + &.parallel { + grid-template-columns: 50px 1fr !important; + } + } + &.inline-diff-view .diff-grid-3-col { grid-template-columns: 50px 50px 1fr !important; } @@ -1209,3 +1202,10 @@ table.code { position: absolute; bottom: 100vh; } + +.diff-line-expand-button { + &:hover, + &:focus { + @include gl-bg-gray-200; + } +} diff --git a/app/assets/stylesheets/highlight/common.scss b/app/assets/stylesheets/highlight/common.scss index bd327082e20..9d479df64c0 100644 --- a/app/assets/stylesheets/highlight/common.scss +++ b/app/assets/stylesheets/highlight/common.scss @@ -19,7 +19,17 @@ background: $dark-diff-match-color; } -@mixin diff-expansion($background, $border, $link) { +@mixin diff-expansion($background, $color, $hover-background, $hover-color) { + background-color: $background; + color: $color; + + &:hover { + background-color: $hover-background; + color: $hover-color; + } +} + +@mixin old-diff-expansion($background, $border, $link) { background-color: $background; .diff-td, @@ -49,6 +59,13 @@ } } + +@mixin dark-diff-expansion-line { + &.expansion .diff-td { + background-color: $dark-diff-match-color; + } +} + @mixin line-coverage-border-color($coverage, $no-coverage) { transition: border-left 0.1s ease-out; diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss index c51b1f04757..0eeebdb2e7a 100644 --- a/app/assets/stylesheets/highlight/themes/dark.scss +++ b/app/assets/stylesheets/highlight/themes/dark.scss @@ -154,8 +154,12 @@ $dark-il: #de935f; color: $dark-line-color; } - .line_expansion { - @include diff-expansion($dark-main-bg, $dark-border, $dark-na); + .old-line_expansion { + @include old-diff-expansion($dark-main-bg, $dark-border, $dark-na); + } + + .diff-line-expand-button { + @include diff-expansion($gray-600, $gray-200, $gray-300, $white); } // Diff line @@ -166,6 +170,10 @@ $dark-il: #de935f; @include dark-diff-match-line; } + &.diff-grid-row { + @include dark-diff-expansion-line; + } + .diff-td.diff-line-num.hll:not(.empty-cell), .diff-td.line-coverage.hll:not(.empty-cell), .diff-td.line-codequality.hll:not(.empty-cell), diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss index 270f81c5cba..b8cd97d6504 100644 --- a/app/assets/stylesheets/highlight/themes/monokai.scss +++ b/app/assets/stylesheets/highlight/themes/monokai.scss @@ -125,8 +125,12 @@ $monokai-gh: #75715e; color: $monokai-text-color; } - .line_expansion { - @include diff-expansion($monokai-bg, $monokai-border, $monokai-k); + .old-line_expansion { + @include old-diff-expansion($monokai-bg, $monokai-border, $monokai-k); + } + + .diff-line-expand-button { + @include diff-expansion($gray-600, $gray-200, $gray-300, $white); } // Diff line @@ -137,6 +141,10 @@ $monokai-gh: #75715e; @include dark-diff-match-line; } + &.diff-grid-row { + @include dark-diff-expansion-line; + } + .diff-td.diff-line-num.hll:not(.empty-cell), .diff-td.line-coverage.hll:not(.empty-cell), .diff-td.line-codequality.hll:not(.empty-cell), diff --git a/app/assets/stylesheets/highlight/themes/none.scss b/app/assets/stylesheets/highlight/themes/none.scss index 7a36aba8be7..99a3de23c26 100644 --- a/app/assets/stylesheets/highlight/themes/none.scss +++ b/app/assets/stylesheets/highlight/themes/none.scss @@ -44,10 +44,15 @@ color: $gl-text-color; } - .line_expansion { - @include diff-expansion($gray-light, $white-normal, $gl-text-color); + .old-line_expansion { + @include old-diff-expansion($gray-light, $white-normal, $gl-text-color); } + .diff-line-expand-button { + @include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800); + } + + // Diff line $none-expanded-border: #e0e0e0; $none-expanded-bg: #e0e0e0; diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss index d01706446c0..55d17b8f1d2 100644 --- a/app/assets/stylesheets/highlight/themes/solarized-dark.scss +++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss @@ -128,8 +128,12 @@ $solarized-dark-il: #2aa198; color: $solarized-dark-pre-color; } - .line_expansion { - @include diff-expansion($solarized-dark-line-bg, $solarized-dark-border, $solarized-dark-kd); + .old-line_expansion { + @include old-diff-expansion($solarized-dark-line-bg, $solarized-dark-border, $solarized-dark-kd); + } + + .diff-line-expand-button { + @include diff-expansion(lighten($solarized-dark-pre-bg, 10%), $gray-200, lighten($solarized-dark-pre-bg, 20%), $white); } // Diff line @@ -140,6 +144,10 @@ $solarized-dark-il: #2aa198; @include dark-diff-match-line; } + &.diff-grid-row { + @include dark-diff-expansion-line; + } + .diff-td.diff-line-num.hll:not(.empty-cell), .diff-td.line-coverage.hll:not(.empty-cell), .diff-td.line-codequality.hll:not(.empty-cell), diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss index a4ce29b7bad..72b961097e4 100644 --- a/app/assets/stylesheets/highlight/themes/solarized-light.scss +++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss @@ -134,9 +134,13 @@ $solarized-light-il: #2aa198; background-color: $solarized-light-pre-bg; color: $solarized-light-pre-color; } + + .old-line_expansion { + @include old-diff-expansion($solarized-light-line-bg, $solarized-light-border, $solarized-light-kd); + } - .line_expansion { - @include diff-expansion($solarized-light-line-bg, $solarized-light-border, $solarized-light-kd); + .diff-line-expand-button { + @include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800); } // Diff line @@ -147,6 +151,10 @@ $solarized-light-il: #2aa198; @include match-line; } + &.diff-grid-row.expansion .diff-td { + background-color: $solarized-light-matchline-bg; + } + .diff-td.diff-line-num.hll:not(.empty-cell), .diff-td.line-coverage.hll:not(.empty-cell), .diff-td.line-codequality.hll:not(.empty-cell), diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss index 20a36d2e8b1..b984c194033 100644 --- a/app/assets/stylesheets/highlight/white_base.scss +++ b/app/assets/stylesheets/highlight/white_base.scss @@ -77,6 +77,22 @@ $white-gc-bg: #eaf2f5; background-color: $gray-light; } +@mixin diff-match-line { + &.expansion { + &.match .diff-td { + color: $gray-400; + } + + .diff-td { + background-color: $gray-50; + + &:first-child { + border-color: $gray-100; + } + } + } +} + // Line numbers .file-line-num { @include line-number-link($black-transparent); @@ -117,8 +133,8 @@ pre.code, color: $white-code-color; } -.line_expansion { - @include diff-expansion($gray-light, $border-color, $blue-600); +.old-line_expansion { + @include old-diff-expansion($gray-light, $border-color, $blue-600); &.diff-tr:last-child { border-bottom-right-radius: 4px; @@ -130,6 +146,10 @@ pre.code, } } +.diff-line-expand-button { + @include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800); +} + // Diff line .line_holder { &.match .line_content, @@ -138,6 +158,10 @@ pre.code, @include match-line; } + &.diff-grid-row { + @include diff-match-line; + } + &:not(.match) .diff-grid-left:hover, &:not(.match) .diff-grid-right:hover, &.code-search-line:hover { diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 47f82471937..4e6e23ad4e6 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -44,6 +44,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:secure_vulnerability_training, project, default_enabled: :yaml) push_frontend_feature_flag(:issue_assignees_widget, @project, default_enabled: :yaml) push_frontend_feature_flag(:realtime_labels, project, default_enabled: :yaml) + push_frontend_feature_flag(:updated_diff_expansion_buttons, project, default_enabled: :yaml) end before_action do diff --git a/app/serializers/ci/job_entity.rb b/app/serializers/ci/job_entity.rb index fca3dec74d4..b6b11e54a16 100644 --- a/app/serializers/ci/job_entity.rb +++ b/app/serializers/ci/job_entity.rb @@ -8,6 +8,7 @@ module Ci expose :name expose :started?, as: :started + expose :started_at, if: -> (job) { job.started? } expose :complete?, as: :complete expose :archived?, as: :archived diff --git a/app/views/shared/snippets/_snippet.html.haml b/app/views/shared/snippets/_snippet.html.haml index 4e373dda013..3cd70dab4d5 100644 --- a/app/views/shared/snippets/_snippet.html.haml +++ b/app/views/shared/snippets/_snippet.html.haml @@ -4,21 +4,20 @@ %li.snippet-row.py-3{ data: { qa_selector: 'snippet_link', qa_snippet_title: snippet.title } } = image_tag avatar_icon_for_user(snippet.author), class: "avatar s40 d-none d-sm-block", alt: '' - .title - = link_to gitlab_snippet_path(snippet) do - = snippet.title + = link_to gitlab_snippet_path(snippet), class: "title" do + = snippet.title - %ul.controls{ data: { qa_selector: 'snippet_file_count_content', qa_snippet_files: snippet.statistics&.file_count } } - %li - = snippet_file_count(snippet) - %li - = link_to gitlab_snippet_path(snippet, anchor: 'notes'), class: ('no-comments' if notes_count == 0) do - = sprite_icon('comments', css_class: 'gl-vertical-align-text-bottom') - = notes_count - %li - %span.sr-only{ data: { qa_selector: 'snippet_visibility_content', qa_snippet_visibility: visibility_level_label(snippet.visibility_level) } } - = visibility_level_label(snippet.visibility_level) - = visibility_level_icon(snippet.visibility_level) + %ul.controls{ data: { qa_selector: 'snippet_file_count_content', qa_snippet_files: snippet.statistics&.file_count } } + %li + = snippet_file_count(snippet) + %li + = link_to gitlab_snippet_path(snippet, anchor: 'notes'), class: ('no-comments' if notes_count == 0) do + = sprite_icon('comments', css_class: 'gl-vertical-align-text-bottom') + = notes_count + %li + %span.sr-only{ data: { qa_selector: 'snippet_visibility_content', qa_snippet_visibility: visibility_level_label(snippet.visibility_level) } } + = visibility_level_label(snippet.visibility_level) + = visibility_level_icon(snippet.visibility_level) .snippet-info #{snippet.to_reference} · diff --git a/config/feature_flags/development/updated_diff_expansion_buttons.yml b/config/feature_flags/development/updated_diff_expansion_buttons.yml new file mode 100644 index 00000000000..70efa024168 --- /dev/null +++ b/config/feature_flags/development/updated_diff_expansion_buttons.yml @@ -0,0 +1,8 @@ +--- +name: updated_diff_expansion_buttons +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80890 +rollout_issue_url: +milestone: '14.10' +type: development +group: group::code review +default_enabled: false diff --git a/data/deprecations/14-10-dependency-scanning-default-java-version.yml b/data/deprecations/14-10-dependency-scanning-default-java-version.yml new file mode 100644 index 00000000000..4616592f00c --- /dev/null +++ b/data/deprecations/14-10-dependency-scanning-default-java-version.yml @@ -0,0 +1,16 @@ +- name: "Dependency Scanning default Java version changed to 17" + announcement_milestone: "14.10" + announcement_date: "2022-04-22" + removal_milestone: "15.0" + removal_date: "2021-05-22" + breaking_change: true + reporter: NicoleSchwartz + body: | + In GitLab 15.0, for Dependency Scanning, the default version of Java will be updated to 17. This is the same as [the most up-to-date Long Term Support (LTS) version](https://en.wikipedia.org/wiki/Java_version_history). GitLab still [supports the same versions as it does today (8, 11, 13, 14, 15, 16, 17)](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning). Only the enabled default is changing. To change the default, set the `DS_Java_Version` variable. +# The following items are not published on the docs page, but may be used in the future. + stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth + tiers: ultimate # (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: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning + 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 diff --git a/data/deprecations/14-5-certificate-based-integration-with-kubernetes-saas.yml b/data/deprecations/14-5-certificate-based-integration-with-kubernetes-saas.yml new file mode 100644 index 00000000000..ebc850a9529 --- /dev/null +++ b/data/deprecations/14-5-certificate-based-integration-with-kubernetes-saas.yml @@ -0,0 +1,17 @@ +- name: "SaaS certificate-based integration with Kubernetes" + announcement_milestone: "14.5" + announcement_date: "2021-11-15" + removal_milestone: "15.0" + removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed + breaking_change: true + body: | + The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab SaaS customer, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0. + + For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the + [agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html) + + For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8). + stage: Configure + tiers: [Free, 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' diff --git a/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml b/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml index 5cf9354cd05..c38da0e3c07 100644 --- a/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml +++ b/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml @@ -1,27 +1,21 @@ -- name: "Certificate-based integration with Kubernetes" +- name: "Self-managed certificate-based integration with Kubernetes" announcement_milestone: "14.5" announcement_date: "2021-11-15" removal_milestone: "15.6" removal_date: "2022-11-22" # the date of the milestone release when this feature is planned to be removed breaking_change: true body: | - [The certificate-based integration with Kubernetes will be deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). + The certificate-based integration with Kubernetes [will be deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). - If you are a self-managed customer, in GitLab 15.0, a feature flag will be introduced so you can keep - certificate-based integration enabled. The flag will be disabled by default. - The flag and the related code will be removed in GitLab 15.6. + As a self-managed customer, we are introducing a feature flag in GitLab 15.0 so you can keep your certificate-based integration enabled. However, the feature flag will be disabled by default, so this change is a **breaking change**. - Until the final removal in 15.6, features built on the integration will continue to work, and - GitLab will continue to fix security and critical issues. - - If you use GitLab.com, certificate-based integrations will cease functioning in 15.0. + In GitLab 15.6 we will remove both the feature, and its related code. Until the final removal in 15.6, features built on this integration will continue to work, if you enable the feature flag. Until the feature is removed, GitLab will continue to fix security and critical issues as they arise. For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the - [agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. - See the documentation for [how to migrate](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html). + [agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html) For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8). stage: Configure - tiers: [Free, Silver, Gold, Core, Premium, Ultimate] + tiers: [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' diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md index dcfa6dffa9d..f77a6c8eec2 100644 --- a/doc/update/deprecations.md +++ b/doc/update/deprecations.md @@ -44,6 +44,18 @@ Most of the deprecations are **planned for removal in 15.0**, and many of them a ## 14.10 +### Dependency Scanning default Java version changed to 17 + +WARNING: +This feature will be changed or removed in 15.0 +as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes). +Before updating GitLab, review the details carefully to determine if you need to make any +changes to your code, settings, or workflow. + +In GitLab 15.0, for Dependency Scanning, the default version of Java will be updated to 17. This is the same as [the most up-to-date Long Term Support (LTS) version](https://en.wikipedia.org/wiki/Java_version_history). GitLab still [supports the same versions as it does today (8, 11, 13, 14, 15, 16, 17)](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning). Only the enabled default is changing. To change the default, set the `DS_Java_Version` variable. + +**Planned removal milestone: 15.0 (2021-05-22)** + ### Manual iteration management WARNING: @@ -1250,33 +1262,6 @@ If you have explicitly excluded bundler-audit using DS_EXCLUDED_ANALYZERS you wi ## 14.5 -### Certificate-based integration with Kubernetes - -WARNING: -This feature will be changed or removed in 15.6 -as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes). -Before updating GitLab, review the details carefully to determine if you need to make any -changes to your code, settings, or workflow. - -[The certificate-based integration with Kubernetes will be deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). - -If you are a self-managed customer, in GitLab 15.0, a feature flag will be introduced so you can keep -certificate-based integration enabled. The flag will be disabled by default. -The flag and the related code will be removed in GitLab 15.6. - -Until the final removal in 15.6, features built on the integration will continue to work, and -GitLab will continue to fix security and critical issues. - -If you use GitLab.com, certificate-based integrations will cease functioning in 15.0. - -For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the -[agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. -See the documentation for [how to migrate](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html). - -For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8). - -**Planned removal milestone: 15.6 (2022-11-22)** - ### Converting an instance (shared) runner to a project (specific) runner WARNING: @@ -1349,6 +1334,44 @@ When checking if a runner is `paused`, API users are advised to check the boolea **Planned removal milestone: 16.0 (2023-04-22)** +### SaaS certificate-based integration with Kubernetes + +WARNING: +This feature will be changed or removed in 15.0 +as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes). +Before updating GitLab, review the details carefully to determine if you need to make any +changes to your code, settings, or workflow. + +The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab SaaS customer, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0. + +For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the +[agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html) + +For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8). + +**Planned removal milestone: 15.0 (2022-05-22)** + +### Self-managed certificate-based integration with Kubernetes + +WARNING: +This feature will be changed or removed in 15.6 +as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes). +Before updating GitLab, review the details carefully to determine if you need to make any +changes to your code, settings, or workflow. + +The certificate-based integration with Kubernetes [will be deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). + +As a self-managed customer, we are introducing a feature flag in GitLab 15.0 so you can keep your certificate-based integration enabled. However, the feature flag will be disabled by default, so this change is a **breaking change**. + +In GitLab 15.6 we will remove both the feature, and its related code. Until the final removal in 15.6, features built on this integration will continue to work, if you enable the feature flag. Until the feature is removed, GitLab will continue to fix security and critical issues as they arise. + +For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the +[agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html) + +For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8). + +**Planned removal milestone: 15.6 (2022-11-22)** + ### Support for SLES 12 SP2 WARNING: diff --git a/doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md b/doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md index 61ec0a559f0..b956b1a6f9c 100644 --- a/doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md +++ b/doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md @@ -14,9 +14,11 @@ To connect your Kubernetes cluster with GitLab, you can use: The certificate-based integration is [**deprecated**](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/) -in GitLab 14.5. It is expected to be -[turned off by default in 15.0](../../../update/deprecations.md#certificate-based-integration-with-kubernetes) -and removed in GitLab 15.6. +in GitLab 14.5. The removal dates are: + +- [GitLab.com customers](../../../update/deprecations.md#saas-certificate-based-integration-with-kubernetes): GitLab 15.0. +- [Self-managed customers](../../../update/deprecations.md#self-managed-certificate-based-integration-with-kubernetes): + Placed behind a disabled feature flag in GitLab 15.0, and removed entirely in GitLab 15.6. If you are using the certificate-based integration, you should move to another workflow as soon as possible. diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 52d5dc827b2..a16ec4a6cc0 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -13076,9 +13076,18 @@ msgid_plural "Diffs|%d deletions" msgstr[0] "" msgstr[1] "" +msgid "Diffs|Expand all lines" +msgstr "" + +msgid "Diffs|Next 20 lines" +msgstr "" + msgid "Diffs|No file name available" msgstr "" +msgid "Diffs|Previous 20 lines" +msgstr "" + msgid "Diffs|Show %{unfoldCount} lines" msgstr "" 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 c06019f6b77..b6f528ceb8b 100644 --- a/spec/features/merge_request/user_comments_on_diff_spec.rb +++ b/spec/features/merge_request/user_comments_on_diff_spec.rb @@ -154,7 +154,7 @@ RSpec.describe 'User comments on a diff', :js do it 'allows comments on previously hidden lines the middle of a file' do # Click 27, expand up, select 18, add and verify comment page.within find_by_scrolling('[data-path="files/ruby/popen.rb"]') do - all('.js-unfold-all')[1].click + first('.js-unfold-all').click end click_diff_line(find('div[data-path="files/ruby/popen.rb"] .left-side a[data-linenumber="21"]').find(:xpath, '../..'), 'left') add_comment('18', '21') @@ -163,10 +163,10 @@ RSpec.describe 'User comments on a diff', :js do it 'allows comments on previously hidden lines at the bottom of a file' do # Click +28, expand down, select 37 add and verify comment page.within find_by_scrolling('[data-path="files/ruby/popen.rb"]') do - all('.js-unfold-down:not([disabled])')[1].click + first('.js-unfold-down').click end click_diff_line(find('div[data-path="files/ruby/popen.rb"] .left-side a[data-linenumber="30"]').find(:xpath, '../..'), 'left') - add_comment('+28', '37') + add_comment('+28', '30') end end diff --git a/spec/features/merge_request/user_views_diffs_spec.rb b/spec/features/merge_request/user_views_diffs_spec.rb index 208ed1f01e7..894292c99eb 100644 --- a/spec/features/merge_request/user_views_diffs_spec.rb +++ b/spec/features/merge_request/user_views_diffs_spec.rb @@ -30,7 +30,7 @@ RSpec.describe 'User views diffs', :js do it 'unfolds diffs in the middle' do page.within('.file-holder[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd"]') do - all('.js-unfold-all')[1].click + first('.js-unfold-all').click expect(page).to have_selector('[data-interop-type="new"] [data-linenumber="24"]', count: 1) expect(page).not_to have_selector('[data-interop-type="new"] [data-linenumber="1"]') diff --git a/spec/frontend/diffs/components/diff_expansion_cell_spec.js b/spec/frontend/diffs/components/diff_expansion_cell_spec.js index cd472920bb9..bd538996349 100644 --- a/spec/frontend/diffs/components/diff_expansion_cell_spec.js +++ b/spec/frontend/diffs/components/diff_expansion_cell_spec.js @@ -20,7 +20,6 @@ function makeLoadMoreLinesPayload({ sinceLine, toLine, oldLineNumber, - diffViewType, fileHash, nextLineNumbers = {}, unfold = false, @@ -28,12 +27,11 @@ function makeLoadMoreLinesPayload({ isExpandDown = false, }) { return { - endpoint: 'contextLinesPath', + endpoint: diffFileMockData.context_lines_path, params: { since: sinceLine, to: toLine, offset: toLine + 1 - oldLineNumber, - view: diffViewType, unfold, bottom, }, @@ -70,10 +68,11 @@ describe('DiffExpansionCell', () => { const createComponent = (options = {}) => { const defaults = { fileHash: mockFile.file_hash, - contextLinesPath: 'contextLinesPath', line: mockLine, isTop: false, isBottom: false, + file: mockFile, + inline: true, }; const propsData = { ...defaults, ...options }; @@ -124,7 +123,7 @@ describe('DiffExpansionCell', () => { describe('any row', () => { [ - { diffViewType: INLINE_DIFF_VIEW_TYPE, lineIndex: 8, file: { parallel_diff_lines: [] } }, + { diffViewType: INLINE_DIFF_VIEW_TYPE, lineIndex: 8, file: cloneDeep(diffFileMockData) }, ].forEach(({ diffViewType, file, lineIndex }) => { describe(`with diffViewType (${diffViewType})`, () => { beforeEach(() => { @@ -140,12 +139,12 @@ describe('DiffExpansionCell', () => { it('on expand all clicked, dispatch loadMoreLines', () => { const oldLineNumber = mockLine.meta_data.old_pos; const newLineNumber = mockLine.meta_data.new_pos; - const previousIndex = getPreviousLineIndex(diffViewType, mockFile, { + const previousIndex = getPreviousLineIndex(mockFile, { oldLineNumber, newLineNumber, }); - const wrapper = createComponent(); + const wrapper = createComponent({ file }); findExpandAll(wrapper).click(); @@ -156,7 +155,6 @@ describe('DiffExpansionCell', () => { toLine: newLineNumber - 1, sinceLine: previousIndex, oldLineNumber, - diffViewType, }), ); }); @@ -168,7 +166,7 @@ describe('DiffExpansionCell', () => { const oldLineNumber = mockLine.meta_data.old_pos; const newLineNumber = mockLine.meta_data.new_pos; - const wrapper = createComponent(); + const wrapper = createComponent({ file }); findExpandUp(wrapper).trigger('click'); @@ -196,17 +194,16 @@ describe('DiffExpansionCell', () => { mockLine.meta_data.old_pos = 200; mockLine.meta_data.new_pos = 200; - const wrapper = createComponent(); + const wrapper = createComponent({ file }); findExpandDown(wrapper).trigger('click'); expect(store.dispatch).toHaveBeenCalledWith('diffs/loadMoreLines', { - endpoint: 'contextLinesPath', + endpoint: diffFileMockData.context_lines_path, params: { since: 1, to: 21, // the load amount, plus 1 line offset: 0, - view: diffViewType, unfold: true, bottom: true, }, diff --git a/spec/frontend/diffs/store/mutations_spec.js b/spec/frontend/diffs/store/mutations_spec.js index d8611b1ce1b..57e623b843d 100644 --- a/spec/frontend/diffs/store/mutations_spec.js +++ b/spec/frontend/diffs/store/mutations_spec.js @@ -131,7 +131,14 @@ describe('DiffsStoreMutations', () => { const options = { lineNumbers: { oldLineNumber: 1, newLineNumber: 2 }, contextLines: [ - { old_line: 1, new_line: 1, line_code: 'ff9200_1_1', discussions: [], hasForm: false }, + { + old_line: 1, + new_line: 1, + line_code: 'ff9200_1_1', + discussions: [], + hasForm: false, + type: 'expanded', + }, ], fileHash: 'ff9200', params: { diff --git a/spec/frontend/diffs/store/utils_spec.js b/spec/frontend/diffs/store/utils_spec.js index 03bcaab0d2b..8ae51a58819 100644 --- a/spec/frontend/diffs/store/utils_spec.js +++ b/spec/frontend/diffs/store/utils_spec.js @@ -51,21 +51,19 @@ describe('DiffsStoreUtils', () => { }); describe('getPreviousLineIndex', () => { - describe(`with diffViewType (inline) in split diffs`, () => { - let diffFile; + let diffFile; - beforeEach(() => { - diffFile = { ...clone(diffFileMockData) }; - }); + beforeEach(() => { + diffFile = { ...clone(diffFileMockData) }; + }); - it('should return the correct previous line number', () => { - expect( - utils.getPreviousLineIndex(INLINE_DIFF_VIEW_TYPE, diffFile, { - oldLineNumber: 3, - newLineNumber: 5, - }), - ).toBe(4); - }); + it('should return the correct previous line number', () => { + expect( + utils.getPreviousLineIndex(diffFile, { + oldLineNumber: 3, + newLineNumber: 5, + }), + ).toBe(4); }); }); diff --git a/spec/serializers/ci/job_entity_spec.rb b/spec/serializers/ci/job_entity_spec.rb index ba68b9a6c16..625beeb239c 100644 --- a/spec/serializers/ci/job_entity_spec.rb +++ b/spec/serializers/ci/job_entity_spec.rb @@ -128,6 +128,15 @@ RSpec.describe Ci::JobEntity do end end + context 'when job is running' do + let_it_be(:job) { create(:ci_build, :running) } + + it 'contains started_at' do + expect(subject[:started]).to be_truthy + expect(subject[:started_at]).to eq(job.started_at) + end + end + context 'when job is generic commit status' do let(:job) { create(:generic_commit_status, target_url: 'http://google.com') } |