diff --git a/.editorconfig b/.editorconfig index 4d9252b..e270271 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,453 +1,466 @@ -# Version: 4.1.1 (Using https://semver.org/) -# Updated: 2022-05-23 -# See https://github.com/RehanSaeed/EditorConfig/releases for release notes. -# See https://github.com/RehanSaeed/EditorConfig for updates to this file. -# See http://EditorConfig.org for more information about .editorconfig files. +; EditorConfig to support per-solution formatting. +; Use the EditorConfig VS add-in to make this work. +; http://editorconfig.org/ +; +; Here are some resources for what's supported for .NET/C# +; https://kent-boogaart.com/blog/editorconfig-reference-for-c-developers +; https://learn.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference +; +; Be **careful** editing this because some of the rules don't support adding a severity level +; For instance if you change to `dotnet_sort_system_directives_first = true:warning` (adding `:warning`) +; then the rule will be silently ignored. -########################################## -# Common Settings -########################################## - -# This file is the top-most EditorConfig file +; This is the default for the codeline. root = true -# All Files +; For disabling MA0048 and MA0051 in a specific folder, e.g., Migrations +[**/Migrations/*.cs] +dotnet_diagnostic.MA0048.severity = none +dotnet_diagnostic.MA0051.severity = none + [*] -charset = utf-8 indent_style = space -indent_size = 4 -insert_final_newline = true +charset = utf-8 trim_trailing_whitespace = true +insert_final_newline = true -########################################## -# File Extension Settings -########################################## - -# Visual Studio Solution Files -[*.sln] -indent_style = tab - -# Visual Studio XML Project Files -[*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}] -indent_size = 2 - -# XML Configuration Files -[*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}] -indent_size = 2 - -# JSON Files -[*.{json,json5,webmanifest}] -indent_size = 2 - -# YAML Files -[*.{yml,yaml}] -indent_size = 2 - -# Markdown Files -[*.{md,mdx}] -trim_trailing_whitespace = false - -# Web Files -[*.{htm,html,js,jsm,ts,tsx,cjs,cts,ctsx,mjs,mts,mtsx,css,sass,scss,less,pcss,svg,vue}] -indent_size = 2 - -# Batch Files -[*.{cmd,bat}] -end_of_line = crlf - -# Bash Files -[*.sh] -end_of_line = lf - -# Makefiles -[Makefile] -indent_style = tab - -########################################## -# Default .NET Code Style Severities -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/configuration-options#scope -########################################## - -[*.{cs,csx,cake,vb,vbx}] -# Default Severity for all .NET Code Style rules below -dotnet_analyzer_diagnostic.severity = warning - -########################################## -# Language Rules -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules -########################################## - -# .NET Style Rules -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#net-style-rules -[*.{cs,csx,cake,vb,vbx}] -# "this." and "Me." qualifiers -dotnet_style_qualification_for_field = true:warning -dotnet_style_qualification_for_property = true:warning -dotnet_style_qualification_for_method = true:warning -dotnet_style_qualification_for_event = true:warning -# Language keywords instead of framework type names for type references -dotnet_style_predefined_type_for_locals_parameters_members = true:warning -dotnet_style_predefined_type_for_member_access = true:warning -# Modifier preferences -dotnet_style_require_accessibility_modifiers = always:warning -csharp_preferred_modifier_order = public, private, protected, internal, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, volatile, async:warning -visual_basic_preferred_modifier_order = Partial, Default, Private, Protected, Public, Friend, NotOverridable, Overridable, MustOverride, Overloads, Overrides, MustInherit, NotInheritable, Static, Shared, Shadows, ReadOnly, WriteOnly, Dim, Const, WithEvents, Widening, Narrowing, Custom, Async:warning -dotnet_style_readonly_field = true:warning -# Parentheses preferences -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning -dotnet_style_parentheses_in_other_operators = never_if_unnecessary:warning -# Expression-level preferences -dotnet_style_object_initializer = true:warning -dotnet_style_collection_initializer = true:warning -dotnet_style_explicit_tuple_names = true:warning -dotnet_style_prefer_inferred_tuple_names = true:warning -dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning -dotnet_style_prefer_auto_properties = true:warning -dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion -dotnet_diagnostic.IDE0045.severity = suggestion -dotnet_style_prefer_conditional_expression_over_return = false:suggestion -dotnet_diagnostic.IDE0046.severity = suggestion -dotnet_style_prefer_compound_assignment = true:warning -dotnet_style_prefer_simplified_interpolation = true:warning -dotnet_style_prefer_simplified_boolean_expressions = true:warning -# Null-checking preferences -dotnet_style_coalesce_expression = true:warning -dotnet_style_null_propagation = true:warning -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning -# File header preferences -# file_header_template = \n© PROJECT-AUTHOR\n -# If you use StyleCop, you'll need to disable SA1636: File header copyright text should match. -# dotnet_diagnostic.SA1636.severity = none -# Undocumented -dotnet_style_operator_placement_when_wrapping = end_of_line:warning -csharp_style_prefer_null_check_over_type_check = true:warning - -# C# Style Rules -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#c-style-rules -[*.{cs,csx,cake}] -# 'var' preferences -csharp_style_var_for_built_in_types = true:warning -csharp_style_var_when_type_is_apparent = true:warning -csharp_style_var_elsewhere = true:warning -# Expression-bodied members -csharp_style_expression_bodied_methods = true:warning -csharp_style_expression_bodied_constructors = true:warning -csharp_style_expression_bodied_operators = true:warning -csharp_style_expression_bodied_properties = true:warning -csharp_style_expression_bodied_indexers = true:warning -csharp_style_expression_bodied_accessors = true:warning -csharp_style_expression_bodied_lambdas = true:warning -csharp_style_expression_bodied_local_functions = true:warning -# Pattern matching preferences -csharp_style_pattern_matching_over_is_with_cast_check = true:warning -csharp_style_pattern_matching_over_as_with_null_check = true:warning -csharp_style_prefer_switch_expression = true:warning -csharp_style_prefer_pattern_matching = true:warning -csharp_style_prefer_not_pattern = true:warning -# Expression-level preferences -csharp_style_inlined_variable_declaration = true:warning -csharp_prefer_simple_default_expression = true:warning -csharp_style_pattern_local_over_anonymous_function = true:warning -csharp_style_deconstructed_variable_declaration = true:warning -csharp_style_prefer_index_operator = true:warning -csharp_style_prefer_range_operator = true:warning -csharp_style_implicit_object_creation_when_type_is_apparent = true:warning -# "Null" checking preferences -csharp_style_throw_expression = true:warning -csharp_style_conditional_delegate_call = true:warning -# Code block preferences -csharp_prefer_braces = true:warning -csharp_prefer_simple_using_statement = true:suggestion -dotnet_diagnostic.IDE0063.severity = suggestion -# 'using' directive preferences -csharp_using_directive_placement = inside_namespace:warning -# Modifier preferences -csharp_prefer_static_local_function = true:warning - -########################################## -# Unnecessary Code Rules -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/unnecessary-code-rules -########################################## - -# .NET Unnecessary code rules -[*.{cs,csx,cake,vb,vbx}] -dotnet_code_quality_unused_parameters = all:warning -dotnet_remove_unnecessary_suppression_exclusions = none:warning - -# C# Unnecessary code rules -[*.{cs,csx,cake}] -csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion -dotnet_diagnostic.IDE0058.severity = suggestion -csharp_style_unused_value_assignment_preference = discard_variable:suggestion -dotnet_diagnostic.IDE0059.severity = suggestion - -########################################## -# Formatting Rules -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules -########################################## - -# .NET formatting rules -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#net-formatting-rules -[*.{cs,csx,cake,vb,vbx}] -# Organize using directives +[*.cs] +indent_size = 4 dotnet_sort_system_directives_first = true -dotnet_separate_import_directive_groups = false -# Dotnet namespace options -dotnet_style_namespace_match_folder = true:suggestion -dotnet_diagnostic.IDE0130.severity = suggestion -# C# formatting rules -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#c-formatting-rules -[*.{cs,csx,cake}] -# Newline options -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#new-line-options +# Don't use this. qualifier +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion + +# use int x = .. over Int32 +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion + +# use int.MaxValue over Int32.MaxValue +dotnet_style_predefined_type_for_member_access = true:suggestion + +# Require var all the time. +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion + +# Disallow throw expressions. +csharp_style_throw_expression = false:suggestion + +# Newline settings csharp_new_line_before_open_brace = all csharp_new_line_before_else = true csharp_new_line_before_catch = true csharp_new_line_before_finally = true csharp_new_line_before_members_in_object_initializers = true csharp_new_line_before_members_in_anonymous_types = true -csharp_new_line_between_query_expression_clauses = true -# Indentation options -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#indentation-options -csharp_indent_case_contents = true -csharp_indent_switch_labels = true -csharp_indent_labels = no_change -csharp_indent_block_contents = true -csharp_indent_braces = false -csharp_indent_case_contents_when_block = false -# Spacing options -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#spacing-options -csharp_space_after_cast = false -csharp_space_after_keywords_in_control_flow_statements = true -csharp_space_between_parentheses = false -csharp_space_before_colon_in_inheritance_clause = true -csharp_space_after_colon_in_inheritance_clause = true -csharp_space_around_binary_operators = before_and_after -csharp_space_between_method_declaration_parameter_list_parentheses = false -csharp_space_between_method_declaration_empty_parameter_list_parentheses = false -csharp_space_between_method_declaration_name_and_open_parenthesis = false -csharp_space_between_method_call_parameter_list_parentheses = false -csharp_space_between_method_call_empty_parameter_list_parentheses = false -csharp_space_between_method_call_name_and_opening_parenthesis = false -csharp_space_after_comma = true -csharp_space_before_comma = false -csharp_space_after_dot = false -csharp_space_before_dot = false -csharp_space_after_semicolon_in_for_statement = true -csharp_space_before_semicolon_in_for_statement = false -csharp_space_around_declaration_statements = false -csharp_space_before_open_square_brackets = false -csharp_space_between_empty_square_brackets = false -csharp_space_between_square_brackets = false -# Wrap options -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#wrap-options -csharp_preserve_single_line_statements = false -csharp_preserve_single_line_blocks = true -# Namespace options -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#namespace-options -csharp_style_namespace_declarations = file_scoped:warning -########################################## -# .NET Naming Rules -# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/naming-rules -########################################## +# Namespace settings +csharp_style_namespace_declarations = file_scoped -[*.{cs,csx,cake,vb,vbx}] +# Brace settings +csharp_prefer_braces = true # Prefer curly braces even for one line of code -########################################## -# Styles -########################################## - -# camel_case_style - Define the camelCase style -dotnet_naming_style.camel_case_style.capitalization = camel_case -# pascal_case_style - Define the PascalCase style +# name all constant fields using PascalCase +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const dotnet_naming_style.pascal_case_style.capitalization = pascal_case -# first_upper_style - The first character must start with an upper-case character -dotnet_naming_style.first_upper_style.capitalization = first_word_upper -# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I' -dotnet_naming_style.prefix_interface_with_i_style.capitalization = pascal_case -dotnet_naming_style.prefix_interface_with_i_style.required_prefix = I -# prefix_type_parameters_with_t_style - Generic Type Parameters must be PascalCase and the first character must be a 'T' -dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization = pascal_case -dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T -# disallowed_style - Anything that has this style applied is marked as disallowed -dotnet_naming_style.disallowed_style.capitalization = pascal_case -dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____ -dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____ -# internal_error_style - This style should never occur... if it does, it indicates a bug in file or in the parser using the file -dotnet_naming_style.internal_error_style.capitalization = pascal_case -dotnet_naming_style.internal_error_style.required_prefix = ____INTERNAL_ERROR____ -dotnet_naming_style.internal_error_style.required_suffix = ____INTERNAL_ERROR____ -########################################## -# .NET Design Guideline Field Naming Rules -# Naming rules for fields follow the .NET Framework design guidelines -# https://docs.microsoft.com/dotnet/standard/design-guidelines/index -########################################## +# internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case -# All public/protected/protected_internal constant fields must be PascalCase -# https://docs.microsoft.com/dotnet/standard/design-guidelines/field -dotnet_naming_symbols.public_protected_constant_fields_group.applicable_accessibilities = public, protected, protected_internal -dotnet_naming_symbols.public_protected_constant_fields_group.required_modifiers = const -dotnet_naming_symbols.public_protected_constant_fields_group.applicable_kinds = field -dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.symbols = public_protected_constant_fields_group -dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.style = pascal_case_style -dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.severity = warning +[*.{xml,config,*proj,nuspec,props,resx,targets,yml,tasks}] +indent_size = 2 -# All public/protected/protected_internal static readonly fields must be PascalCase -# https://docs.microsoft.com/dotnet/standard/design-guidelines/field -dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_accessibilities = public, protected, protected_internal -dotnet_naming_symbols.public_protected_static_readonly_fields_group.required_modifiers = static, readonly -dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_kinds = field -dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.symbols = public_protected_static_readonly_fields_group -dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style -dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.severity = warning +# Xml config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 2 -# No other public/protected/protected_internal fields are allowed -# https://docs.microsoft.com/dotnet/standard/design-guidelines/field -dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibilities = public, protected, protected_internal -dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = field -dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols = other_public_protected_fields_group -dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style -dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error +[*.json] +indent_size = 2 -########################################## -# StyleCop Field Naming Rules -# Naming rules for fields follow the StyleCop analyzers -# This does not override any rules using disallowed_style above -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers -########################################## +[*.{ps1,psm1}] +indent_size = 4 -# All constant fields must be PascalCase -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md -dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private -dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const -dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field -dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group -dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = pascal_case_style -dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity = warning +[*.sh] +indent_size = 4 +end_of_line = lf -# All static readonly fields must be PascalCase -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md -dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private -dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly -dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field -dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group -dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style -dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity = warning +[*.{razor,cshtml}] +charset = utf-8-bom -# No non-private instance fields are allowed -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md -dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected -dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field -dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group -dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style -dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.severity = error +[*.{cs,vb}] -# Private fields must be camelCase -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1306.md -dotnet_naming_symbols.stylecop_private_fields_group.applicable_accessibilities = private -dotnet_naming_symbols.stylecop_private_fields_group.applicable_kinds = field -dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.symbols = stylecop_private_fields_group -dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.style = camel_case_style -dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.severity = warning +# SYSLIB1054: Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time +dotnet_diagnostic.SYSLIB1054.severity = warning -# Local variables must be camelCase -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md -dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local -dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local -dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group -dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style -dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.severity = silent +# CA1018: Mark attributes with AttributeUsageAttribute +dotnet_diagnostic.CA1018.severity = warning -# This rule should never fire. However, it's included for at least two purposes: -# First, it helps to understand, reason about, and root-case certain types of issues, such as bugs in .editorconfig parsers. -# Second, it helps to raise immediate awareness if a new field type is added (as occurred recently in C#). -dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_accessibilities = * -dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_kinds = field -dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols = sanity_check_uncovered_field_case_group -dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style = internal_error_style -dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity = error +# CA1047: Do not declare protected member in sealed type +dotnet_diagnostic.CA1047.severity = warning +# CA1305: Specify IFormatProvider +dotnet_diagnostic.CA1305.severity = warning -########################################## -# Other Naming Rules -########################################## +# CA1507: Use nameof to express symbol names +dotnet_diagnostic.CA1507.severity = warning -# All of the following must be PascalCase: -# - Namespaces -# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-namespaces -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md -# - Classes and Enumerations -# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md -# - Delegates -# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces#names-of-common-types -# - Constructors, Properties, Events, Methods -# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-type-members -dotnet_naming_symbols.element_group.applicable_kinds = namespace, class, enum, struct, delegate, event, method, property -dotnet_naming_rule.element_rule.symbols = element_group -dotnet_naming_rule.element_rule.style = pascal_case_style -dotnet_naming_rule.element_rule.severity = warning +# CA1510: Use ArgumentNullException throw helper +dotnet_diagnostic.CA1510.severity = warning -# Interfaces use PascalCase and are prefixed with uppercase 'I' -# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces -dotnet_naming_symbols.interface_group.applicable_kinds = interface -dotnet_naming_rule.interface_rule.symbols = interface_group -dotnet_naming_rule.interface_rule.style = prefix_interface_with_i_style -dotnet_naming_rule.interface_rule.severity = warning +# CA1511: Use ArgumentException throw helper +dotnet_diagnostic.CA1511.severity = warning -# Generics Type Parameters use PascalCase and are prefixed with uppercase 'T' -# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces -dotnet_naming_symbols.type_parameter_group.applicable_kinds = type_parameter -dotnet_naming_rule.type_parameter_rule.symbols = type_parameter_group -dotnet_naming_rule.type_parameter_rule.style = prefix_type_parameters_with_t_style -dotnet_naming_rule.type_parameter_rule.severity = warning +# CA1512: Use ArgumentOutOfRangeException throw helper +dotnet_diagnostic.CA1512.severity = warning -# Function parameters use camelCase -# https://docs.microsoft.com/dotnet/standard/design-guidelines/naming-parameters -dotnet_naming_symbols.parameters_group.applicable_kinds = parameter -dotnet_naming_rule.parameters_rule.symbols = parameters_group -dotnet_naming_rule.parameters_rule.style = camel_case_style -dotnet_naming_rule.parameters_rule.severity = warning +# CA1513: Use ObjectDisposedException throw helper +dotnet_diagnostic.CA1513.severity = warning -# Disable warnings for using LoggerMessage delegates -dotnet_diagnostic.CA1848.severity = none +# CA1725: Parameter names should match base declaration +dotnet_diagnostic.CA1725.severity = suggestion -########################################## -# License -########################################## -# The following applies as to the .editorconfig file ONLY, and is -# included below for reference, per the requirements of the license -# corresponding to this .editorconfig file. -# See: https://github.com/RehanSaeed/EditorConfig -# -# MIT License -# -# Copyright (c) 2017-2019 Muhammad Rehan Saeed -# Copyright (c) 2019 Henry Gabryjelski -# -# 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. -########################################## \ No newline at end of file +# CA1802: Use literals where appropriate +dotnet_diagnostic.CA1802.severity = warning + +# CA1805: Do not initialize unnecessarily +dotnet_diagnostic.CA1805.severity = warning + +# CA1810: Do not initialize unnecessarily +dotnet_diagnostic.CA1810.severity = warning + +# CA1821: Remove empty Finalizers +dotnet_diagnostic.CA1821.severity = warning + +# CA1822: Make member static +dotnet_diagnostic.CA1822.severity = warning +dotnet_code_quality.CA1822.api_surface = private, internal + +# CA1823: Avoid unused private fields +dotnet_diagnostic.CA1823.severity = warning + +# CA1825: Avoid zero-length array allocations +dotnet_diagnostic.CA1825.severity = warning + +# CA1826: Do not use Enumerable methods on indexable collections. Instead use the collection directly +dotnet_diagnostic.CA1826.severity = warning + +# CA1827: Do not use Count() or LongCount() when Any() can be used +dotnet_diagnostic.CA1827.severity = warning + +# CA1828: Do not use CountAsync() or LongCountAsync() when AnyAsync() can be used +dotnet_diagnostic.CA1828.severity = warning + +# CA1829: Use Length/Count property instead of Count() when available +dotnet_diagnostic.CA1829.severity = warning + +# CA1830: Prefer strongly-typed Append and Insert method overloads on StringBuilder +dotnet_diagnostic.CA1830.severity = warning + +# CA1831: Use AsSpan or AsMemory instead of Range-based indexers when appropriate +dotnet_diagnostic.CA1831.severity = warning + +# CA1832: Use AsSpan or AsMemory instead of Range-based indexers when appropriate +dotnet_diagnostic.CA1832.severity = warning + +# CA1833: Use AsSpan or AsMemory instead of Range-based indexers when appropriate +dotnet_diagnostic.CA1833.severity = warning + +# CA1834: Consider using 'StringBuilder.Append(char)' when applicable +dotnet_diagnostic.CA1834.severity = warning + +# CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync' +dotnet_diagnostic.CA1835.severity = warning + +# CA1836: Prefer IsEmpty over Count +dotnet_diagnostic.CA1836.severity = warning + +# CA1837: Use 'Environment.ProcessId' +dotnet_diagnostic.CA1837.severity = warning + +# CA1838: Avoid 'StringBuilder' parameters for P/Invokes +dotnet_diagnostic.CA1838.severity = warning + +# CA1839: Use 'Environment.ProcessPath' +dotnet_diagnostic.CA1839.severity = warning + +# CA1840: Use 'Environment.CurrentManagedThreadId' +dotnet_diagnostic.CA1840.severity = warning + +# CA1841: Prefer Dictionary.Contains methods +dotnet_diagnostic.CA1841.severity = warning + +# CA1842: Do not use 'WhenAll' with a single task +dotnet_diagnostic.CA1842.severity = warning + +# CA1843: Do not use 'WaitAll' with a single task +dotnet_diagnostic.CA1843.severity = warning + +# CA1844: Provide memory-based overrides of async methods when subclassing 'Stream' +dotnet_diagnostic.CA1844.severity = warning + +# CA1845: Use span-based 'string.Concat' +dotnet_diagnostic.CA1845.severity = warning + +# CA1846: Prefer AsSpan over Substring +dotnet_diagnostic.CA1846.severity = warning + +# CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters +dotnet_diagnostic.CA1847.severity = warning + +# CA1852: Seal internal types +dotnet_diagnostic.CA1852.severity = warning + +# CA1854: Prefer the IDictionary.TryGetValue(TKey, out TValue) method +dotnet_diagnostic.CA1854.severity = warning + +# CA1855: Prefer 'Clear' over 'Fill' +dotnet_diagnostic.CA1855.severity = warning + +# CA1856: Incorrect usage of ConstantExpected attribute +dotnet_diagnostic.CA1856.severity = error + +# CA1857: A constant is expected for the parameter +dotnet_diagnostic.CA1857.severity = warning + +# CA1858: Use 'StartsWith' instead of 'IndexOf' +dotnet_diagnostic.CA1858.severity = warning + +# CA2007: Consider calling ConfigureAwait on the awaited task +dotnet_diagnostic.CA2007.severity = warning + +# CA2008: Do not create tasks without passing a TaskScheduler +dotnet_diagnostic.CA2008.severity = warning + +# CA2009: Do not call ToImmutableCollection on an ImmutableCollection value +dotnet_diagnostic.CA2009.severity = warning + +# CA2011: Avoid infinite recursion +dotnet_diagnostic.CA2011.severity = warning + +# CA2012: Use ValueTask correctly +dotnet_diagnostic.CA2012.severity = warning + +# CA2013: Do not use ReferenceEquals with value types +dotnet_diagnostic.CA2013.severity = warning + +# CA2014: Do not use stackalloc in loops. +dotnet_diagnostic.CA2014.severity = warning + +# CA2016: Forward the 'CancellationToken' parameter to methods that take one +dotnet_diagnostic.CA2016.severity = warning + +# CA2200: Rethrow to preserve stack details +dotnet_diagnostic.CA2200.severity = warning + +# CA2201: Do not raise reserved exception types +dotnet_diagnostic.CA2201.severity = warning + +# CA2208: Instantiate argument exceptions correctly +dotnet_diagnostic.CA2208.severity = warning + +# CA2245: Do not assign a property to itself +dotnet_diagnostic.CA2245.severity = warning + +# CA2246: Assigning symbol and its member in the same statement +dotnet_diagnostic.CA2246.severity = warning + +# CA2249: Use string.Contains instead of string.IndexOf to improve readability. +dotnet_diagnostic.CA2249.severity = warning + +# IDE0005: Remove unnecessary usings +dotnet_diagnostic.IDE0005.severity = warning + +# IDE0011: Curly braces to surround blocks of code +dotnet_diagnostic.IDE0011.severity = warning + +# IDE0020: Use pattern matching to avoid is check followed by a cast (with variable) +dotnet_diagnostic.IDE0020.severity = warning + +# IDE0029: Use coalesce expression (non-nullable types) +dotnet_diagnostic.IDE0029.severity = warning + +# IDE0030: Use coalesce expression (nullable types) +dotnet_diagnostic.IDE0030.severity = warning + +# IDE0031: Use null propagation +dotnet_diagnostic.IDE0031.severity = warning + +# IDE0035: Remove unreachable code +dotnet_diagnostic.IDE0035.severity = warning + +# IDE0036: Order modifiers +csharp_preferred_modifier_order = public, private, protected, internal, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, volatile, async:suggestion +dotnet_diagnostic.IDE0036.severity = warning + +# IDE0038: Use pattern matching to avoid is check followed by a cast (without variable) +dotnet_diagnostic.IDE0038.severity = warning + +# IDE0043: Format string contains invalid placeholder +dotnet_diagnostic.IDE0043.severity = warning + +# IDE0044: Make field readonly +dotnet_diagnostic.IDE0044.severity = warning + +# IDE0051: Remove unused private members +dotnet_diagnostic.IDE0051.severity = warning + +# IDE0055: All formatting rules +dotnet_diagnostic.IDE0055.severity = suggestion + +# IDE0059: Unnecessary assignment to a value +dotnet_diagnostic.IDE0059.severity = warning + +# IDE0060: Remove unused parameter +dotnet_code_quality_unused_parameters = non_public +dotnet_diagnostic.IDE0060.severity = warning + +# IDE0062: Make local function static +dotnet_diagnostic.IDE0062.severity = warning + +# IDE0073: File header +dotnet_diagnostic.IDE0073.severity = warning +# Not a dotnet foundation project +#file_header_template = Licensed to the .NET Foundation under one or more agreements.\nThe .NET Foundation licenses this file to you under the MIT license. + +# IDE0161: Convert to file-scoped namespace +dotnet_diagnostic.IDE0161.severity = warning + +# IDE0200: Lambda expression can be removed +dotnet_diagnostic.IDE0200.severity = warning + +# IDE2000: Disallow multiple blank lines +dotnet_style_allow_multiple_blank_lines_experimental = false +dotnet_diagnostic.IDE2000.severity = warning + +[{eng/tools/**.cs,**/{test,testassets,samples,Samples,perf,benchmarkapps,scripts,stress}/**.cs,src/Hosting/Server.IntegrationTesting/**.cs,src/Servers/IIS/IntegrationTesting.IIS/**.cs,src/Shared/Http2cat/**.cs,src/Testing/**.cs}] +# CA1018: Mark attributes with AttributeUsageAttribute +dotnet_diagnostic.CA1018.severity = suggestion +# CA1507: Use nameof to express symbol names +dotnet_diagnostic.CA1507.severity = suggestion +# CA1510: Use ArgumentNullException throw helper +dotnet_diagnostic.CA1510.severity = suggestion +# CA1511: Use ArgumentException throw helper +dotnet_diagnostic.CA1511.severity = suggestion +# CA1512: Use ArgumentOutOfRangeException throw helper +dotnet_diagnostic.CA1512.severity = suggestion +# CA1513: Use ObjectDisposedException throw helper +dotnet_diagnostic.CA1513.severity = suggestion +# CA1802: Use literals where appropriate +dotnet_diagnostic.CA1802.severity = suggestion +# CA1805: Do not initialize unnecessarily +dotnet_diagnostic.CA1805.severity = suggestion +# CA1810: Do not initialize unnecessarily +dotnet_diagnostic.CA1810.severity = suggestion +# CA1822: Make member static +dotnet_diagnostic.CA1822.severity = suggestion +# CA1823: Avoid zero-length array allocations +dotnet_diagnostic.CA1825.severity = suggestion +# CA1826: Do not use Enumerable methods on indexable collections. Instead use the collection directly +dotnet_diagnostic.CA1826.severity = suggestion +# CA1827: Do not use Count() or LongCount() when Any() can be used +dotnet_diagnostic.CA1827.severity = suggestion +# CA1829: Use Length/Count property instead of Count() when available +dotnet_diagnostic.CA1829.severity = suggestion +# CA1831: Use AsSpan or AsMemory instead of Range-based indexers when appropriate +dotnet_diagnostic.CA1831.severity = suggestion +# CA1832: Use AsSpan or AsMemory instead of Range-based indexers when appropriate +dotnet_diagnostic.CA1832.severity = suggestion +# CA1833: Use AsSpan or AsMemory instead of Range-based indexers when appropriate +dotnet_diagnostic.CA1833.severity = suggestion +# CA1834: Consider using 'StringBuilder.Append(char)' when applicable +dotnet_diagnostic.CA1834.severity = suggestion +# CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync' +dotnet_diagnostic.CA1835.severity = suggestion +# CA1837: Use 'Environment.ProcessId' +dotnet_diagnostic.CA1837.severity = suggestion +# CA1838: Avoid 'StringBuilder' parameters for P/Invokes +dotnet_diagnostic.CA1838.severity = suggestion +# CA1841: Prefer Dictionary.Contains methods +dotnet_diagnostic.CA1841.severity = suggestion +# CA1844: Provide memory-based overrides of async methods when subclassing 'Stream' +dotnet_diagnostic.CA1844.severity = suggestion +# CA1845: Use span-based 'string.Concat' +dotnet_diagnostic.CA1845.severity = suggestion +# CA1846: Prefer AsSpan over Substring +dotnet_diagnostic.CA1846.severity = suggestion +# CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters +dotnet_diagnostic.CA1847.severity = suggestion +# CA1852: Seal internal types +dotnet_diagnostic.CA1852.severity = suggestion +# CA1854: Prefer the IDictionary.TryGetValue(TKey, out TValue) method +dotnet_diagnostic.CA1854.severity = suggestion +# CA1855: Prefer 'Clear' over 'Fill' +dotnet_diagnostic.CA1855.severity = suggestion +# CA1856: Incorrect usage of ConstantExpected attribute +dotnet_diagnostic.CA1856.severity = suggestion +# CA1857: A constant is expected for the parameter +dotnet_diagnostic.CA1857.severity = suggestion +# CA1858: Use 'StartsWith' instead of 'IndexOf' +dotnet_diagnostic.CA1858.severity = suggestion +# CA2007: Consider calling ConfigureAwait on the awaited task +dotnet_diagnostic.CA2007.severity = suggestion +# CA2008: Do not create tasks without passing a TaskScheduler +dotnet_diagnostic.CA2008.severity = suggestion +# CA2012: Use ValueTask correctly +dotnet_diagnostic.CA2012.severity = suggestion +# CA2201: Do not raise reserved exception types +dotnet_diagnostic.CA2201.severity = suggestion +# CA2249: Use string.Contains instead of string.IndexOf to improve readability. +dotnet_diagnostic.CA2249.severity = suggestion +# IDE0005: Remove unnecessary usings +dotnet_diagnostic.IDE0005.severity = suggestion +# IDE0020: Use pattern matching to avoid is check followed by a cast (with variable) +dotnet_diagnostic.IDE0020.severity = suggestion +# IDE0029: Use coalesce expression (non-nullable types) +dotnet_diagnostic.IDE0029.severity = suggestion +# IDE0030: Use coalesce expression (nullable types) +dotnet_diagnostic.IDE0030.severity = suggestion +# IDE0031: Use null propagation +dotnet_diagnostic.IDE0031.severity = suggestion +# IDE0038: Use pattern matching to avoid is check followed by a cast (without variable) +dotnet_diagnostic.IDE0038.severity = suggestion +# IDE0044: Make field readonly +dotnet_diagnostic.IDE0044.severity = suggestion +# IDE0051: Remove unused private members +dotnet_diagnostic.IDE0051.severity = suggestion +# IDE0059: Unnecessary assignment to a value +dotnet_diagnostic.IDE0059.severity = suggestion +# IDE0060: Remove unused parameters +dotnet_diagnostic.IDE0060.severity = suggestion +# IDE0062: Make local function static +dotnet_diagnostic.IDE0062.severity = suggestion +# IDE0200: Lambda expression can be removed +dotnet_diagnostic.IDE0200.severity = suggestion + +# CA2016: Forward the 'CancellationToken' parameter to methods that take one +dotnet_diagnostic.CA2016.severity = suggestion + +# Defaults for content in the shared src/ and shared runtime dir + +[{**/Shared/runtime/**.{cs,vb},src/Shared/test/Shared.Tests/runtime/**.{cs,vb},**/microsoft.extensions.hostfactoryresolver.sources/**.{cs,vb}}] +# CA1822: Make member static +dotnet_diagnostic.CA1822.severity = silent +# IDE0011: Use braces +dotnet_diagnostic.IDE0011.severity = silent +# IDE0055: Fix formatting +dotnet_diagnostic.IDE0055.severity = silent +# IDE0060: Remove unused parameters +dotnet_diagnostic.IDE0060.severity = silent +# IDE0062: Make local function static +dotnet_diagnostic.IDE0062.severity = silent +# IDE0161: Convert to file-scoped namespace +dotnet_diagnostic.IDE0161.severity = silent + +[{**/Shared/**.cs,**/microsoft.extensions.hostfactoryresolver.sources/**.{cs,vb}}] +# IDE0005: Remove unused usings. Ignore for shared src files since imports for those depend on the projects in which they are included. +dotnet_diagnostic.IDE0005.severity = silent \ No newline at end of file diff --git a/.gitea/workflows/server.yaml b/.gitea/workflows/server.yaml index 95239b7..bdb37bf 100644 --- a/.gitea/workflows/server.yaml +++ b/.gitea/workflows/server.yaml @@ -1,13 +1,171 @@ -name: Test if Server can be built +name: Build, Package and Push Images run-name: ${{ gitea.actor }} is building the Server application on: [ push ] jobs: - build-server: + preprocess: + runs-on: ubuntu-latest + outputs: + sanitized_branch_name: ${{ steps.sanitize.outputs.sanitized_branch_name }} steps: - - uses: actions/checkout@v3 - - name: Setup dotnet - uses: https://github.com/actions/setup-dotnet@v3 - with: - global-json-file: global.json - - run: dotnet build Server + - name: Sanitize branch name + id: sanitize + run: echo "::set-output name=sanitized_branch_name::$(echo ${{ github.ref_name }} | sed 's/\//-/g')" + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup dotnet + uses: https://github.com/actions/setup-dotnet@v3 + with: + dotnet-version: 8.0 + - name: Install dependencies + run: dotnet restore + - name: Build + run: | + dotnet build Server -c Release + # dotnet test Server.Tests -c Release + + sonarqube: + needs: build + runs-on: ubuntu-latest + if: github.ref_name == 'master' + steps: + - uses: actions/checkout@v3 + - name: Setup dotnet + uses: https://github.com/actions/setup-dotnet@v3 + with: + dotnet-version: 8.0 + - name: Install dependencies + run: | + dotnet restore + echo "::add-path::$HOME/.dotnet/tools" + - name: Setup Sonarqube Dependencies + run: | + apt-get update + apt-get install --yes openjdk-11-jre + dotnet tool install --global dotnet-sonarscanner + dotnet tool install --global dotnet-coverage + - name: Sonarqube Begin + run: | + dotnet sonarscanner begin /key:"${{ secrets.SONAR_PROJECT_KEY }}" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="${{ secrets.SONAR_HOST_URL }}" + - name: Sonarqube Scan + run: | + dotnet build Server -c Release + # dotnet test --collect "Code Coverage" --logger trx --results-directory "TestsResults" + # dotnet-coverage collect 'dotnet test' -f xml -o 'coverage.xml' + - name: Sonarqube End + run: | + dotnet sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" + + sbom-scan: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup dotnet + uses: https://github.com/actions/setup-dotnet@v3 + with: + dotnet-version: | + 7.0 + 8.0 + - name: Install dependencies + run: | + dotnet restore + echo "::add-path::$HOME/.dotnet/tools" + - name: Setup Dependency Track Dependencies + run: | + dotnet tool install --global CycloneDX + - name: Generate SBOM + run: | + dotnet CycloneDX Server/Server.csproj -o . -dgl + - name: Upload SBOM + uses: https://github.com/DependencyTrack/gh-upload-sbom@v2.0.1 + with: + apiKey: ${{ secrets.DEPENDENCY_TRACK_API_KEY }} + serverHostname: ${{ secrets.DEPENDENCY_TRACK_URL }} + projectName: ${{ secrets.DEPENDENCY_TRACK_PROJECT_NAME }} + autoCreate: true + # set projectversion to be the branch name + projectVersion: "${{ github.ref_name }}" + bomFilename: "${{ github.workspace }}/bom.xml" + + container-build: + runs-on: ubuntu-latest + container: catthehacker/ubuntu:act-latest + needs: [ build, preprocess ] + steps: + - uses: actions/checkout@v3 + - name: Setup dotnet + uses: https://github.com/actions/setup-dotnet@v3 + with: + dotnet-version: 8.0 + # Add support for more platforms with QEMU (optional) + # https://github.com/docker/setup-qemu-action + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + registry: ${{ github.server_url }} + username: ${{ github.actor }} + password: ${{ secrets.REGISTRY_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + file: Server/Dockerfile + push: true + tags: forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }} + platforms: linux/amd64,linux/arm64 + - name: Build and push to latest + if: github.ref_name == 'master' + uses: docker/build-push-action@v5 + with: + context: . + file: Server/Dockerfile + push: true + tags: forge.rainote.dev/${{ github.repository }}:latest + platforms: linux/amd64, linux/arm64 + + container-sbom-scan: + needs: [ container-build, preprocess ] + runs-on: ubuntu-latest + container: catthehacker/ubuntu:act-latest + steps: + - uses: actions/checkout@v3 + - name: Setup dotnet + uses: https://github.com/actions/setup-dotnet@v3 + with: + dotnet-version: 8.0 + - name: Install dependencies + run: | + dotnet restore + echo "::add-path::$HOME/.dotnet/tools" + - name: Setup Dependency Track Dependencies + run: | + mkdir ~/.docker + curl -sSfL https://raw.githubusercontent.com/docker/sbom-cli-plugin/main/install.sh | sh -s -- + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + registry: ${{ github.server_url }} + username: ${{ github.actor }} + password: ${{ secrets.REGISTRY_TOKEN }} + - name: Generate SBOM + run: | + docker sbom forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }} --format cyclonedx-json --output bom.json + - name: Upload SBOM + uses: https://github.com/DependencyTrack/gh-upload-sbom@v2.0.1 + with: + apiKey: ${{ secrets.DEPENDENCY_TRACK_API_KEY }} + serverHostname: ${{ secrets.DEPENDENCY_TRACK_URL }} + projectName: "${{ secrets.DEPENDENCY_TRACK_PROJECT_NAME }}-container" + autoCreate: true + # set projectversion to be the branch name + projectVersion: "${{ github.ref_name }}" + bomFilename: "${{ github.workspace }}/bom.json" + diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index 3a39862..8b71371 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -5,11 +5,15 @@ enable enable preview - net6.0;net7.0;net8.0 + net6.0;net7.0 - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Benchmarks/BinaryConversionBenchmarks.cs b/Benchmarks/BinaryConversionBenchmarks.cs index 820502d..74cef4c 100644 --- a/Benchmarks/BinaryConversionBenchmarks.cs +++ b/Benchmarks/BinaryConversionBenchmarks.cs @@ -14,30 +14,30 @@ using BenchmarkDotNet.Order; [ThreadingDiagnoser] public class BinaryConversionBenchmarks { - private byte[] data; - private int offset; + private byte[] _data = null!; + private int _offset; [GlobalSetup] public void Setup() { - this.data = RandomNumberGenerator.GetBytes(4000); - this.offset = RandomNumberGenerator.GetInt32(0, 3500); + this._data = RandomNumberGenerator.GetBytes(4000); + this._offset = RandomNumberGenerator.GetInt32(0, 3500); } [Benchmark] - public short BitConverterTest() => BitConverter.ToInt16(this.data, this.offset); + public short BitConverterTest() => BitConverter.ToInt16(this._data, this._offset); [Benchmark] public short BinaryReader() { - using var ms = new MemoryStream(this.data); + using var ms = new MemoryStream(this._data); using var reader = new BinaryReader(ms); - reader.BaseStream.Position = this.offset; + reader.BaseStream.Position = this._offset; return reader.ReadInt16(); } [Benchmark] public short BinaryPrimitives() => System.Buffers.Binary.BinaryPrimitives.ReadInt16LittleEndian( - new ArraySegment(this.data, this.offset, sizeof(short))); + new ArraySegment(this._data, this._offset, sizeof(short))); } diff --git a/Continuity.sln b/Continuity.sln index 87391ca..a8a1984 100644 --- a/Continuity.sln +++ b/Continuity.sln @@ -4,12 +4,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{7D560FA1-A61C-4B67-8300-835CA5814621}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "build", "build\build.csproj", "{046A3B46-FC08-4B08-A52A-1DC5D426120D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C1303691-99F6-41CE-BAD3-2CA112D75DBF}" - ProjectSection(SolutionItems) = preProject - docker-compose.yml = docker-compose.yml - EndProjectSection +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wonderking", "Wonderking\Wonderking.csproj", "{6B53A10B-C397-4347-BB00-A12272D0528E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,8 +12,6 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {046A3B46-FC08-4B08-A52A-1DC5D426120D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {046A3B46-FC08-4B08-A52A-1DC5D426120D}.Release|Any CPU.ActiveCfg = Release|Any CPU {7EDA8B31-3E03-4CA3-87D1-CFEB05C277D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7EDA8B31-3E03-4CA3-87D1-CFEB05C277D6}.Debug|Any CPU.Build.0 = Debug|Any CPU {7EDA8B31-3E03-4CA3-87D1-CFEB05C277D6}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -27,5 +20,9 @@ Global {7D560FA1-A61C-4B67-8300-835CA5814621}.Debug|Any CPU.Build.0 = Debug|Any CPU {7D560FA1-A61C-4B67-8300-835CA5814621}.Release|Any CPU.ActiveCfg = Release|Any CPU {7D560FA1-A61C-4B67-8300-835CA5814621}.Release|Any CPU.Build.0 = Release|Any CPU + {6B53A10B-C397-4347-BB00-A12272D0528E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B53A10B-C397-4347-BB00-A12272D0528E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B53A10B-C397-4347-BB00-A12272D0528E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B53A10B-C397-4347-BB00-A12272D0528E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/Server/.dockerignore b/Server/.dockerignore new file mode 100644 index 0000000..a72b3bb --- /dev/null +++ b/Server/.dockerignore @@ -0,0 +1,1227 @@ +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### ASPNETCore template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/ + +### VisualStudio template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +### Csharp template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +### Rider template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + diff --git a/Server/AuthSession.cs b/Server/AuthSession.cs index bdc3168..443d3ae 100644 --- a/Server/AuthSession.cs +++ b/Server/AuthSession.cs @@ -1,3 +1,5 @@ +using Wonderking.Packets; + namespace Server; using System.Reflection; @@ -8,28 +10,28 @@ using Packets; public class AuthSession : TcpSession { - private readonly ILogger logger; - private readonly IMediator mediator; + private readonly ILogger _logger; + private readonly IMediator _mediator; public AuthSession(TcpServer server, IMediator mediator, ILogger logger) : base(server) { - this.mediator = mediator; - this.logger = logger; + this._mediator = mediator; + this._logger = logger; } public Guid AccountId { get; set; } public override long Send(byte[] buffer) { - this.logger.LogInformation("Data being sent is: {Data}", BitConverter.ToString(buffer)); + this._logger.LogInformation("Data being sent is: {Data}", BitConverter.ToString(buffer)); return base.Send(buffer); } public void Send(IPacket packet) { var type = packet.GetType(); - this.logger.LogTrace("Packet of type {Type} is being serialized", type.Name); + this._logger.LogTrace("Packet of type {Type} is being serialized", type.Name); var packetIdAttribute = type.GetCustomAttribute(); if (packetIdAttribute == null) { @@ -57,40 +59,40 @@ public class AuthSession : TcpSession buffer[2 + i] = bytesOfOpcode[i]; } - this.logger.LogTrace("Packet data being parsed is: {Data}", BitConverter.ToString(packetData.ToArray())); - this.logger.LogTrace("Packet being parsed is: {Data}", BitConverter.ToString(buffer.ToArray())); + this._logger.LogTrace("Packet data being parsed is: {Data}", BitConverter.ToString(packetData.ToArray())); + this._logger.LogTrace("Packet being parsed is: {Data}", BitConverter.ToString(buffer.ToArray())); this.Send(buffer); } protected override void OnReceived(byte[] buffer, long offset, long size) { - this.logger.LogDebug("Length: {Size} & offset: {Offset}", size, offset); + this._logger.LogDebug("Length: {Size} & offset: {Offset}", size, offset); Span decryptedBuffer = new byte[size]; // xor every value after the first 8 bytes var dataBuffer = Decrypt(new ArraySegment(buffer, 8, (int)size - 8).ToArray()); - this.logger.LogDebug("Length {Length}", BitConverter.ToUInt16(buffer, 0)); + this._logger.LogDebug("Length {Length}", BitConverter.ToUInt16(buffer, 0)); var opCode = BitConverter.ToUInt16(buffer.ToArray(), 2); - this.logger.LogDebug("Packet Op Code: {OpCode}", opCode); - this.logger.LogDebug("Some Value: {RandomValue}", buffer[4]); + this._logger.LogDebug("Packet Op Code: {OpCode}", opCode); + this._logger.LogDebug("Some Value: {RandomValue}", buffer[4]); var clientAliveTime = BitConverter.ToUInt16(buffer.ToArray(), 5); - this.logger.LogDebug("Client Alive time: {ClientAliveTime}", clientAliveTime); - this.logger.LogDebug("Might be a flag: {Flag}", buffer[7]); + this._logger.LogDebug("Client Alive time: {ClientAliveTime}", clientAliveTime); + this._logger.LogDebug("Might be a flag: {Flag}", buffer[7]); - this.logger.LogDebug("Full buffer: {Buffer}", BitConverter.ToString(dataBuffer.ToArray())); + this._logger.LogDebug("Full buffer: {Buffer}", BitConverter.ToString(dataBuffer.ToArray())); var rawPacket = new RawPacket((OperationCode)opCode, dataBuffer, clientAliveTime, buffer[7], buffer[4], this.Id, this); - _ = this.mediator.Send(rawPacket); + _ = this._mediator.Send(rawPacket); - this.logger.LogInformation("Connection from: {@RemoteEndpoint}", this.Socket.RemoteEndPoint?.ToString()); + this._logger.LogInformation("Connection from: {@RemoteEndpoint}", this.Socket.RemoteEndPoint?.ToString()); base.OnReceived(decryptedBuffer.ToArray(), offset, decryptedBuffer.Length); } diff --git a/Server/ChannelSession.cs b/Server/ChannelSession.cs index ae11461..593719e 100644 --- a/Server/ChannelSession.cs +++ b/Server/ChannelSession.cs @@ -8,34 +8,34 @@ using NetCoreServer; public class ChannelSession : TcpSession { - private static readonly byte[] Key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7 } + private static readonly byte[] _key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7 } .Reverse().ToArray(); - private static readonly byte[] Iv = new byte[] + private static readonly byte[] _iv = new byte[] { 0xfe, 220, 0xba, 0x98, 0x76, 0x54, 50, 0x10, 15, 30, 0x2d, 60, 0x4b, 90, 0x69, 120 }.Reverse().ToArray(); - private readonly ICryptoTransform decryptor; + private readonly ICryptoTransform _decryptor; - private readonly ICryptoTransform encryptor; - private readonly ILogger logger; - private readonly IMediator mediator; + private readonly ICryptoTransform _encryptor; + private readonly ILogger _logger; + private readonly IMediator _mediator; public ChannelSession(TcpServer server, IMediator mediator, ILogger logger) : base(server) { - this.mediator = mediator; - this.logger = logger; + this._mediator = mediator; + this._logger = logger; var aes = Aes.Create(); - aes.Key = Key; - aes.IV = Iv; + aes.Key = _key; + aes.IV = _iv; aes.Padding = PaddingMode.None; #pragma warning disable SEC0026 aes.Mode = CipherMode.ECB; #pragma warning restore SEC0026 - this.decryptor = aes.CreateDecryptor(aes.Key, aes.IV); - this.encryptor = aes.CreateEncryptor(aes.Key, aes.IV); + this._decryptor = aes.CreateDecryptor(aes.Key, aes.IV); + this._encryptor = aes.CreateEncryptor(aes.Key, aes.IV); } protected override void OnReceived(byte[] buffer, long offset, long size) @@ -43,12 +43,12 @@ public class ChannelSession : TcpSession try { using (var ms = new MemoryStream(Decrypt(buffer))) - using (var cs = new CryptoStream(ms, this.decryptor, CryptoStreamMode.Read)) + using (var cs = new CryptoStream(ms, this._decryptor, CryptoStreamMode.Read)) { var amountOfReadBytes = cs.Read(buffer); if (amountOfReadBytes != buffer.Length) { - this.logger.LogError("Amount of read bytes is not equal to buffer length."); + this._logger.LogError("Amount of read bytes is not equal to buffer length."); } } @@ -56,8 +56,8 @@ public class ChannelSession : TcpSession } catch (CryptographicException ex) { - this.logger.LogError("An error has occured while decrypting: {ErrorMessage}", ex.Message); - this.logger.LogError("Default buffer message: {Message}", Encoding.ASCII.GetString(buffer)); + this._logger.LogError("An error has occured while decrypting: {ErrorMessage}", ex.Message); + this._logger.LogError("Default buffer message: {Message}", Encoding.ASCII.GetString(buffer)); } } diff --git a/Server/Consumers/PacketConsumer.cs b/Server/Consumers/PacketConsumer.cs index 44c80cf..9b9f7cd 100644 --- a/Server/Consumers/PacketConsumer.cs +++ b/Server/Consumers/PacketConsumer.cs @@ -6,13 +6,13 @@ using Services; public class PacketConsumer : IConsumer { - private readonly PacketDistributorService distributorService; + private readonly PacketDistributorService _distributorService; - public PacketConsumer(PacketDistributorService distributorService) => this.distributorService = distributorService; + public PacketConsumer(PacketDistributorService distributorService) => this._distributorService = distributorService; public Task Consume(ConsumeContext context) { - this.distributorService.AddPacket(context.Message); + this._distributorService.AddPacket(context.Message); return Task.CompletedTask; } } diff --git a/Server/DB/WonderkingContext.cs b/Server/DB/WonderkingContext.cs index 0b33c01..2cc9720 100644 --- a/Server/DB/WonderkingContext.cs +++ b/Server/DB/WonderkingContext.cs @@ -7,13 +7,13 @@ using Microsoft.Extensions.Logging; public class WonderkingContext : DbContext { - private readonly IConfiguration configuration; - private readonly ILoggerFactory loggerFactory; + private readonly IConfiguration _configuration; + private readonly ILoggerFactory _loggerFactory; public WonderkingContext(ILoggerFactory loggerFactory, IConfiguration configuration) { - this.loggerFactory = loggerFactory; - this.configuration = configuration; + this._loggerFactory = loggerFactory; + this._configuration = configuration; } public DbSet Accounts { get; set; } @@ -22,8 +22,8 @@ public class WonderkingContext : DbContext protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder .UseNpgsql( - $"Host={this.configuration["DB:Host"]};Username={this.configuration["DB:Username"]};Password={this.configuration["DB:Password"]};Database={this.configuration["DB:Database"]};Port={this.configuration["DB:Port"]}") - .EnableSensitiveDataLogging().UseLoggerFactory(this.loggerFactory); + $"Host={this._configuration["DB:Host"]};Username={this._configuration["DB:Username"]};Password={this._configuration["DB:Password"]};Database={this._configuration["DB:Database"]};Port={this._configuration["DB:Port"]}") + .EnableSensitiveDataLogging().UseLoggerFactory(this._loggerFactory); protected override void OnModelCreating(ModelBuilder modelBuilder) => modelBuilder.Entity(builder => diff --git a/Server/Dockerfile b/Server/Dockerfile index 5bcbaf6..709b557 100644 --- a/Server/Dockerfile +++ b/Server/Dockerfile @@ -1,18 +1,28 @@ -FROM mcr.microsoft.com/dotnet/runtime:7.0 AS base +FROM mcr.microsoft.com/dotnet/runtime:8.0-bookworm-slim AS base WORKDIR /app -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim AS build +ARG TARGETARCH +ENV TZ=Etc/UTC +ENV DOTNET_TieredPGO=1 +ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 + +RUN echo "Target: $TARGETARCH" +RUN echo "Build: $BUILDPLATFORM" WORKDIR /src +COPY ["Wonderking/Wonderking.csproj", "Wonderking/"] COPY ["Server/Server.csproj", "Server/"] -RUN dotnet restore "Server/Server.csproj" +RUN dotnet restore "Wonderking/Wonderking.csproj" -a $TARGETARCH +RUN dotnet restore "Server/Server.csproj" -a $TARGETARCH COPY . . -WORKDIR "/src/Server" -RUN dotnet build "Server.csproj" -c Release -o /app/build FROM build AS publish -RUN dotnet publish "Server.csproj" -c Release -o /app/publish /p:UseAppHost=false +RUN dotnet publish "Server/Server.csproj" -c Release -a $TARGETARCH --no-restore -f net8.0 -o /app FROM base AS final WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "Server.dll"] +COPY --from=publish /app . +USER $APP_UID +ENTRYPOINT ["./Server"] + + diff --git a/Server/PacketLoggerMessages.cs b/Server/LoggerMessages/PacketLoggerMessages.cs similarity index 97% rename from Server/PacketLoggerMessages.cs rename to Server/LoggerMessages/PacketLoggerMessages.cs index 25257b4..3601281 100644 --- a/Server/PacketLoggerMessages.cs +++ b/Server/LoggerMessages/PacketLoggerMessages.cs @@ -1,8 +1,8 @@ -namespace Server; - using JetBrains.Annotations; using Microsoft.Extensions.Logging; -using Packets; +using Wonderking.Packets; + +namespace Server.LoggerMessages; public static partial class PacketLoggerMessages { @@ -43,7 +43,6 @@ public static partial class PacketLoggerMessages Message = "Packet data {PacketData}")] public static partial void PacketData(this ILogger logger, string packetData); - [LoggerMessage(EventId = 9, Level = LogLevel.Critical, Message = "No Packets have been found")] public static partial void NoPacketsFound(this ILogger logger); diff --git a/Server/PacketHandlers/ChannelSelectionHandler.cs b/Server/PacketHandlers/ChannelSelectionHandler.cs index a8091b0..12c2030 100644 --- a/Server/PacketHandlers/ChannelSelectionHandler.cs +++ b/Server/PacketHandlers/ChannelSelectionHandler.cs @@ -1,23 +1,25 @@ +using Microsoft.EntityFrameworkCore; +using Wonderking.Packets.Incoming; + namespace Server.PacketHandlers; using DB; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using NetCoreServer; -using Packets.Incoming; public class ChannelSelectionHandler : IPacketHandler { - private readonly IConfiguration configuration; - private readonly ILogger logger; - private readonly WonderkingContext wonderkingContext; + private readonly IConfiguration _configuration; + private readonly ILogger _logger; + private readonly WonderkingContext _wonderkingContext; public ChannelSelectionHandler(IConfiguration configuration, ILogger logger, WonderkingContext wonderkingContext) { - this.configuration = configuration; - this.logger = logger; - this.wonderkingContext = wonderkingContext; + this._configuration = configuration; + this._logger = logger; + this._wonderkingContext = wonderkingContext; } public ChannelSelectionHandler() @@ -27,7 +29,9 @@ public class ChannelSelectionHandler : IPacketHandler public Task HandleAsync(ChannelSelectionPacket packet, TcpSession session) { var authSession = (AuthSession)session; - var charactersOfAccount = this.wonderkingContext.Accounts.FirstOrDefault(a => a.Id == authSession.AccountId); + var charactersOfAccount = this._wonderkingContext.Accounts.Include(account => account.Characters) + .FirstOrDefault(a => a.Id == authSession.AccountId) + ?.Characters; return Task.CompletedTask; } } diff --git a/Server/PacketHandlers/IPacketHandler.cs b/Server/PacketHandlers/IPacketHandler.cs index a9f1c86..40448d6 100644 --- a/Server/PacketHandlers/IPacketHandler.cs +++ b/Server/PacketHandlers/IPacketHandler.cs @@ -1,8 +1,9 @@ +using Wonderking.Packets; + namespace Server.PacketHandlers; using JetBrains.Annotations; using NetCoreServer; -using Packets; [UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)] public interface IPacketHandler where T : IPacket diff --git a/Server/PacketHandlers/LoginHandler.cs b/Server/PacketHandlers/LoginHandler.cs index dbd1a65..35dd997 100644 --- a/Server/PacketHandlers/LoginHandler.cs +++ b/Server/PacketHandlers/LoginHandler.cs @@ -1,35 +1,36 @@ -namespace Server.PacketHandlers; - using System.Security.Cryptography; using System.Text; +using Wonderking.Packets.Incoming; +using Wonderking.Packets.Outgoing; + +namespace Server.PacketHandlers; + using DB; using DB.Documents; using Konscious.Security.Cryptography; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using NetCoreServer; -using Packets.Incoming; -using Packets.Outgoing; public class LoginHandler : IPacketHandler { - private readonly IConfiguration configuration; - private readonly ILogger logger; - private readonly WonderkingContext wonderkingContext; + private readonly IConfiguration _configuration; + private readonly ILogger _logger; + private readonly WonderkingContext _wonderkingContext; public LoginHandler(ILogger logger, WonderkingContext wonderkingContext, IConfiguration configuration) { - this.logger = logger; - this.wonderkingContext = wonderkingContext; - this.configuration = configuration; + this._logger = logger; + this._wonderkingContext = wonderkingContext; + this._configuration = configuration; } public async Task HandleAsync(LoginInfoPacket packet, TcpSession session) { LoginResponseReason loginResponseReason; - this.logger.LogInformation("Login data: Username {Username} & Password {Password}", packet.Username, + this._logger.LogInformation("Login data: Username {Username} & Password {Password}", packet.Username, packet.Password); - var account = this.wonderkingContext.Accounts.FirstOrDefault(a => a.Username == packet.Username); + var account = this._wonderkingContext.Accounts.FirstOrDefault(a => a.Username == packet.Username); // https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Chea1t_Sheet.html#argon2id // "Use Argon2id with a minimum configuration of 19 MiB of memory, an iteration count of 2, and 1 degree of parallelism." @@ -41,22 +42,22 @@ public class LoginHandler : IPacketHandler }; if (account == null) { - if (this.configuration.GetSection("Testing").GetValue("CreateAccountOnLogin")) + if (this._configuration.GetSection("Testing").GetValue("CreateAccountOnLogin")) { argon2Id.Salt = RandomNumberGenerator.GetBytes(16); var finalAccount = - await this.wonderkingContext.Accounts.AddAsync(new Account(packet.Username, Array.Empty(), "", + await this._wonderkingContext.Accounts.AddAsync(new Account(packet.Username, Array.Empty(), "", 0, argon2Id.Salt)).ConfigureAwait(true); - await this.wonderkingContext.SaveChangesAsync().ConfigureAwait(true); + await this._wonderkingContext.SaveChangesAsync().ConfigureAwait(true); argon2Id.AssociatedData = finalAccount.Entity.Id.ToByteArray(); finalAccount.Entity.Password = await argon2Id.GetBytesAsync(16).ConfigureAwait(true); - this.wonderkingContext.Accounts.Update(finalAccount.Entity); + this._wonderkingContext.Accounts.Update(finalAccount.Entity); loginResponseReason = LoginResponseReason.Ok; - await this.wonderkingContext.SaveChangesAsync().ConfigureAwait(true); + await this._wonderkingContext.SaveChangesAsync().ConfigureAwait(true); } else { - this.logger.LogInformation("Requested account for user: {Username} does not exist", packet.Username); + this._logger.LogInformation("Requested account for user: {Username} does not exist", packet.Username); loginResponseReason = LoginResponseReason.AccountDoesNotExit; } } @@ -78,12 +79,9 @@ public class LoginHandler : IPacketHandler IsGameMaster = true }; var sess = session as AuthSession; - if (account != null) + if (account != null && sess != null) { - if (sess != null) - { - sess.AccountId = account.Id; - } + sess.AccountId = account.Id; } sess?.Send(loginResponsePacket); diff --git a/Server/Packets/RawPacket.cs b/Server/Packets/RawPacket.cs index 6f96690..11e7ca0 100644 --- a/Server/Packets/RawPacket.cs +++ b/Server/Packets/RawPacket.cs @@ -1,3 +1,5 @@ +using Wonderking.Packets; + namespace Server.Packets; using MassTransit; diff --git a/Server/Program.cs b/Server/Program.cs index 76327dd..3241823 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -1,4 +1,3 @@ -#pragma warning disable AV1500 using System.Net; using System.Reflection; using MassTransit; @@ -35,11 +34,10 @@ builder.Services.AddHostedService(provider => new WonderkingAuthServer(IPAddress provider.GetService() ?? throw new InvalidOperationException())); using var host = builder.Build(); -await using (var scope = host.Services.CreateAsyncScope()) +using (var scope = host.Services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); await db.Database.MigrateAsync().ConfigureAwait(true); } await host.RunAsync().ConfigureAwait(true); -#pragma warning restore AV1500 diff --git a/Server/Server.csproj b/Server/Server.csproj index 34e1cef..cfa8679 100644 --- a/Server/Server.csproj +++ b/Server/Server.csproj @@ -2,13 +2,32 @@ Exe - net7.0 enable warnings Linux Server default true + net8.0;net7.0 + true + strict + Timothy (RaiNote) Schenk + Timothy (RaiNote) Schenk + https://forge.rainote.dev/wonderking/continuity + https://forge.rainote.dev/wonderking/continuity + git + False + True + LICENSE + latest-recommended + + + + 7 + + + + 7 @@ -18,26 +37,35 @@ - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + @@ -68,4 +96,15 @@ Always + + + + True + \ + + + + + + diff --git a/Server/Services/PacketDistributorService.cs b/Server/Services/PacketDistributorService.cs index 65b3b51..79f9c34 100644 --- a/Server/Services/PacketDistributorService.cs +++ b/Server/Services/PacketDistributorService.cs @@ -1,3 +1,6 @@ +using Server.LoggerMessages; +using Wonderking.Packets; + namespace Server.Services; using System.Collections.Concurrent; @@ -17,35 +20,32 @@ using static DotNext.Metaprogramming.CodeGenerator; public class PacketDistributorService : IHostedService { - private readonly ConcurrentQueue concurrentQueue; + private readonly ConcurrentQueue _concurrentQueue; private readonly ImmutableDictionary> deserializationMap; + Func> _deserializationMap; - private readonly ILogger logger; - private readonly ConcurrentDictionary packetHandlersInstantiation; - - private readonly IServiceProvider serviceProvider; + private readonly ILogger _logger; + private readonly ConcurrentDictionary _packetHandlersInstantiation; public PacketDistributorService(ILogger logger, IServiceProvider serviceProvider) { - this.concurrentQueue = new ConcurrentQueue(); - this.logger = logger; - this.serviceProvider = serviceProvider; + this._concurrentQueue = new ConcurrentQueue(); + this._logger = logger; var tempDeserializationMap = new Dictionary>(); var executingAssembly = Assembly.GetExecutingAssembly(); var packetsTypes = this.GetPacketsWithId(executingAssembly); var packetHandlers = this.GetAllPacketHandlersWithId(executingAssembly); - this.packetHandlersInstantiation = new ConcurrentDictionary(); + this._packetHandlersInstantiation = new ConcurrentDictionary(); packetHandlers.ForEach(x => { var packetHandler = - ActivatorUtilities.GetServiceOrCreateInstance(this.serviceProvider, + ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, x.Value); - this.packetHandlersInstantiation.TryAdd(x.Key, packetHandler); + this._packetHandlersInstantiation.TryAdd(x.Key, packetHandler); }); foreach (var packetsType in packetsTypes) { @@ -64,7 +64,7 @@ public class PacketDistributorService : IHostedService tempDeserializationMap.Add(packetsType.Key, lambda); } - this.deserializationMap = tempDeserializationMap.ToImmutableDictionary(); + this._deserializationMap = tempDeserializationMap.ToImmutableDictionary(); } public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask; @@ -82,45 +82,56 @@ public class PacketDistributorService : IHostedService if (packetsWithId is not { Count: 0 }) { packetsWithId.AsParallel() - .ForAll(packet => this.logger.PacketWithIdAdded(packet.Key, packet.Value.FullName)); + .ForAll(packet => this._logger.PacketWithIdAdded(packet.Key, packet.Value.FullName)); return packetsWithId; } - this.logger.NoPacketsFound(); + this._logger.NoPacketsFound(); throw new IncompleteInitialization(); } private Dictionary GetAllPacketHandlersWithId(Assembly assembly) { - var packetHandlersWithId = assembly.GetTypes().AsParallel().Where(t => - t is { IsClass: true, IsAbstract: false } && t - .GetInterfaces().Any(i => - i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketHandler<>))).ToDictionary(type => - type.GetInterfaces().First(t => - t is { IsGenericType: true } && t.GetGenericTypeDefinition() == typeof(IPacketHandler<>)) - .GetGenericArguments().First().GetCustomAttribute().Code); + // ! : We are filtering if types that don't have an instance of the required Attribute + var packetHandlersWithId = assembly.GetTypes().AsParallel() + .Where(t => + t is { IsClass: true, IsAbstract: false } && Array.Exists(t + .GetInterfaces(), i => + i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketHandler<>))) + .Select(type => new + { + Type = type, + PacketId = type + .GetInterfaces().First(t1 => + t1 is { IsGenericType: true } && t1.GetGenericTypeDefinition() == typeof(IPacketHandler<>)) + .GetGenericArguments()[0].GetCustomAttribute()?.Code + }) + .Where(x => x.PacketId is not null) + .ToDictionary( + x => x.PacketId!.Value, x => x.Type + ); if (packetHandlersWithId is not { Count: 0 }) { packetHandlersWithId.AsParallel().ForAll(packetHandler => - this.logger.PacketHandlerWithIdAdded(packetHandler.Key, packetHandler.Value.FullName)); + this._logger.PacketHandlerWithIdAdded(packetHandler.Key, packetHandler.Value.FullName)); return packetHandlersWithId; } - this.logger.NoPacketHandlersFound(); + this._logger.NoPacketHandlersFound(); throw new IncompleteInitialization(); } public void AddPacket(RawPacket rawPacket) { - this.concurrentQueue.Enqueue(rawPacket); + this._concurrentQueue.Enqueue(rawPacket); this.DequeueRawPacket(); - this.logger.PacketReceived(rawPacket.OperationCode); + this._logger.PacketReceived(rawPacket.OperationCode); } private void DequeueRawPacket() { - if (this.concurrentQueue.TryDequeue(out var item)) + if (this._concurrentQueue.TryDequeue(out var item)) { ThreadPool.QueueUserWorkItem(this.InvokePacketHandler, item, true); } @@ -128,18 +139,19 @@ public class PacketDistributorService : IHostedService private void InvokePacketHandler(RawPacket item) { - this.logger.PacketDequeued(item.Session.Id, item.OperationCode); - if (!this.deserializationMap.ContainsKey(item.OperationCode)) + this._logger.PacketDequeued(item.Session.Id, item.OperationCode); + if (!this._deserializationMap.TryGetValue(item.OperationCode, out var value)) { - this.logger.PacketTypeNotFound(item.OperationCode); + this._logger.PacketTypeNotFound(item.OperationCode); return; } - var packet = this.deserializationMap[item.OperationCode](item.MessageBody); - this.logger.PacketData(JsonConvert.SerializeObject(packet)); - this.packetHandlersInstantiation[item.OperationCode].GetType().GetMethod(nameof(IPacketHandler.HandleAsync)) - ?.Invoke(this.packetHandlersInstantiation[item.OperationCode], new object[] { packet, item.Session }); + var packet = value(item.MessageBody); + this._logger.PacketData(JsonConvert.SerializeObject(packet)); + this._packetHandlersInstantiation[item.OperationCode].GetType() + .GetMethod(nameof(IPacketHandler.HandleAsync)) + ?.Invoke(this._packetHandlersInstantiation[item.OperationCode], new object[] { packet, item.Session }); - this.logger.PacketFinished(item.Session.Id, item.OperationCode); + this._logger.PacketFinished(item.Session.Id, item.OperationCode); } } diff --git a/Server/Services/WonderkingAuthServer.cs b/Server/Services/WonderkingAuthServer.cs index 6cbb8e7..fd9d6e1 100644 --- a/Server/Services/WonderkingAuthServer.cs +++ b/Server/Services/WonderkingAuthServer.cs @@ -9,14 +9,14 @@ using NetCoreServer; public class WonderkingAuthServer : TcpServer, IHostedService { - private readonly ILogger logger; - private readonly IServiceProvider serviceProvider; + private readonly ILogger _logger; + private readonly IServiceProvider _serviceProvider; public WonderkingAuthServer(IPAddress address, int port, ILogger logger, IServiceProvider serviceProvider) : base(address, port) { - this.logger = logger; - this.serviceProvider = serviceProvider; + this._logger = logger; + this._serviceProvider = serviceProvider; } public Task StartAsync(CancellationToken cancellationToken) @@ -32,31 +32,31 @@ public class WonderkingAuthServer : TcpServer, IHostedService } protected override TcpSession CreateSession() => - ActivatorUtilities.CreateInstance(this.serviceProvider, this); + ActivatorUtilities.CreateInstance(this._serviceProvider, this); protected override void OnStarting() { - this.logger.LogInformation("Starting"); + this._logger.LogInformation("Starting"); base.OnStarting(); } protected override void OnStarted() { - this.logger.LogInformation("Started"); + this._logger.LogInformation("Started"); base.OnStarted(); } protected override void OnStopping() { - this.logger.LogInformation("Stopping"); + this._logger.LogInformation("Stopping"); base.OnStopping(); } protected override void OnStopped() { - this.logger.LogInformation("Stopped"); + this._logger.LogInformation("Stopped"); base.OnStopped(); } - protected override void OnError(SocketError error) => this.logger.LogError("An error has occured {Error}", error); + protected override void OnError(SocketError error) => this._logger.LogError("An error has occured {Error}", error); } diff --git a/Server/docker-compose.yml b/Server/docker-compose.yml index 5cbd3e9..1efa332 100644 --- a/Server/docker-compose.yml +++ b/Server/docker-compose.yml @@ -1,6 +1,9 @@ services: server: - image: continuity-server:latest + container_name: continuity-server + image: server:latest + depends_on: + - db environment: - ENVIRONMENT=Development - Testing:CreateAccountOnLogin=true @@ -14,6 +17,7 @@ - "10001:10001" db: + container_name: continuity-db image: postgres:16.0-alpine environment: - POSTGRES_USER=continuity @@ -23,6 +27,11 @@ - continuity volumes: - db-data:/var/lib/postgresql/data + healthcheck: + test: [ "CMD-SHELL", "sh -c 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}'" ] + interval: 10s + timeout: 3s + retries: 3 networks: continuity: diff --git a/Server/Packets/IPacket.cs b/Wonderking/Packets/IPacket.cs similarity index 86% rename from Server/Packets/IPacket.cs rename to Wonderking/Packets/IPacket.cs index e5d5317..fa795eb 100644 --- a/Server/Packets/IPacket.cs +++ b/Wonderking/Packets/IPacket.cs @@ -1,7 +1,7 @@ -namespace Server.Packets; - using JetBrains.Annotations; +namespace Wonderking.Packets; + [UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)] public interface IPacket { diff --git a/Server/Packets/Incoming/ChannelSelectionPacket.cs b/Wonderking/Packets/Incoming/ChannelSelectionPacket.cs similarity index 77% rename from Server/Packets/Incoming/ChannelSelectionPacket.cs rename to Wonderking/Packets/Incoming/ChannelSelectionPacket.cs index ea17fb4..c74e385 100644 --- a/Server/Packets/Incoming/ChannelSelectionPacket.cs +++ b/Wonderking/Packets/Incoming/ChannelSelectionPacket.cs @@ -1,4 +1,4 @@ -namespace Server.Packets.Incoming; +namespace Wonderking.Packets.Incoming; [PacketId(OperationCode.ChannelSelection)] public class ChannelSelectionPacket : IPacket @@ -12,5 +12,5 @@ public class ChannelSelectionPacket : IPacket this.ChannelId = BitConverter.ToUInt16(data, 2); } - public byte[] Serialize() => throw new NotImplementedException(); + public byte[] Serialize() => throw new NotSupportedException(); } diff --git a/Server/Packets/Incoming/LoginInfoPacket.cs b/Wonderking/Packets/Incoming/LoginInfoPacket.cs similarity index 96% rename from Server/Packets/Incoming/LoginInfoPacket.cs rename to Wonderking/Packets/Incoming/LoginInfoPacket.cs index 4351884..4758ef7 100644 --- a/Server/Packets/Incoming/LoginInfoPacket.cs +++ b/Wonderking/Packets/Incoming/LoginInfoPacket.cs @@ -1,7 +1,7 @@ -namespace Server.Packets.Incoming; - using System.Text; +namespace Wonderking.Packets.Incoming; + [PacketId(OperationCode.LoginInfo)] public class LoginInfoPacket : IPacket { diff --git a/Server/Packets/OperationCode.cs b/Wonderking/Packets/OperationCode.cs similarity index 77% rename from Server/Packets/OperationCode.cs rename to Wonderking/Packets/OperationCode.cs index 578c544..f8b9eea 100644 --- a/Server/Packets/OperationCode.cs +++ b/Wonderking/Packets/OperationCode.cs @@ -1,4 +1,4 @@ -namespace Server.Packets; +namespace Wonderking.Packets; public enum OperationCode : ushort { diff --git a/Server/Packets/Outgoing/LoginResponsePacket.cs b/Wonderking/Packets/Outgoing/LoginResponsePacket.cs similarity index 98% rename from Server/Packets/Outgoing/LoginResponsePacket.cs rename to Wonderking/Packets/Outgoing/LoginResponsePacket.cs index 63299fe..057d032 100644 --- a/Server/Packets/Outgoing/LoginResponsePacket.cs +++ b/Wonderking/Packets/Outgoing/LoginResponsePacket.cs @@ -1,4 +1,4 @@ -namespace Server.Packets.Outgoing; +namespace Wonderking.Packets.Outgoing; [PacketId(OperationCode.LoginResponse)] public class LoginResponsePacket : IPacket diff --git a/Server/Packets/Outgoing/LoginResponseReason.cs b/Wonderking/Packets/Outgoing/LoginResponseReason.cs similarity index 92% rename from Server/Packets/Outgoing/LoginResponseReason.cs rename to Wonderking/Packets/Outgoing/LoginResponseReason.cs index b4e8bff..adc830f 100644 --- a/Server/Packets/Outgoing/LoginResponseReason.cs +++ b/Wonderking/Packets/Outgoing/LoginResponseReason.cs @@ -1,4 +1,4 @@ -namespace Server.Packets.Outgoing; +namespace Wonderking.Packets.Outgoing; public enum LoginResponseReason : byte { diff --git a/Server/Packets/Outgoing/ServerChannelData.cs b/Wonderking/Packets/Outgoing/ServerChannelData.cs similarity index 60% rename from Server/Packets/Outgoing/ServerChannelData.cs rename to Wonderking/Packets/Outgoing/ServerChannelData.cs index a6eee00..b707c4a 100644 --- a/Server/Packets/Outgoing/ServerChannelData.cs +++ b/Wonderking/Packets/Outgoing/ServerChannelData.cs @@ -1,5 +1,8 @@ -namespace Server.Packets.Outgoing; +using System.Runtime.InteropServices; +namespace Wonderking.Packets.Outgoing; + +[StructLayout(LayoutKind.Auto)] public struct ServerChannelData { public ushort ServerId { get; set; } diff --git a/Server/Packets/PacketIdAttribute.cs b/Wonderking/Packets/PacketIdAttribute.cs similarity index 87% rename from Server/Packets/PacketIdAttribute.cs rename to Wonderking/Packets/PacketIdAttribute.cs index 6638733..e2f2b5a 100644 --- a/Server/Packets/PacketIdAttribute.cs +++ b/Wonderking/Packets/PacketIdAttribute.cs @@ -1,4 +1,4 @@ -namespace Server.Packets; +namespace Wonderking.Packets; [AttributeUsage(AttributeTargets.Class, Inherited = false)] public class PacketIdAttribute : Attribute diff --git a/Wonderking/Wonderking.csproj b/Wonderking/Wonderking.csproj new file mode 100644 index 0000000..e8fbd2c --- /dev/null +++ b/Wonderking/Wonderking.csproj @@ -0,0 +1,34 @@ + + + + enable + enable + net8.0;net7.0 + strict + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/build.cmd b/build.cmd deleted file mode 100644 index b08cc59..0000000 --- a/build.cmd +++ /dev/null @@ -1,7 +0,0 @@ -:; set -eo pipefail -:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) -:; ${SCRIPT_DIR}/build.sh "$@" -:; exit $? - -@ECHO OFF -powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %* diff --git a/build.ps1 b/build.ps1 deleted file mode 100644 index 2719418..0000000 --- a/build.ps1 +++ /dev/null @@ -1,74 +0,0 @@ -[CmdletBinding()] -Param( - [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] - [string[]]$BuildArguments -) - -Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)" - -Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 } -$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent - -########################################################################### -# CONFIGURATION -########################################################################### - -$BuildProjectFile = "$PSScriptRoot\build\build.csproj" -$TempDirectory = "$PSScriptRoot\\.nuke\temp" - -$DotNetGlobalFile = "$PSScriptRoot\\global.json" -$DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1" -$DotNetChannel = "STS" - -$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1 -$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1 -$env:DOTNET_MULTILEVEL_LOOKUP = 0 - -########################################################################### -# EXECUTION -########################################################################### - -function ExecSafe([scriptblock] $cmd) { - & $cmd - if ($LASTEXITCODE) { exit $LASTEXITCODE } -} - -# If dotnet CLI is installed globally and it matches requested version, use for execution -if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and ` - $(dotnet --version) -and $LASTEXITCODE -eq 0) { - $env:DOTNET_EXE = (Get-Command "dotnet").Path -} -else { - # Download install script - $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1" - New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile) - - # If global.json exists, load expected version - if (Test-Path $DotNetGlobalFile) { - $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json) - if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) { - $DotNetVersion = $DotNetGlobal.sdk.version - } - } - - # Install by channel or version - $DotNetDirectory = "$TempDirectory\dotnet-win" - if (!(Test-Path variable:DotNetVersion)) { - ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath } - } else { - ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath } - } - $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe" -} - -Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)" - -if (Test-Path env:NUKE_ENTERPRISE_TOKEN) { - & $env:DOTNET_EXE nuget remove source "nuke-enterprise" > $null - & $env:DOTNET_EXE nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password $env:NUKE_ENTERPRISE_TOKEN > $null -} - -ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet } -ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments } diff --git a/build.sh b/build.sh deleted file mode 100644 index 25e0d46..0000000 --- a/build.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash - -bash --version 2>&1 | head -n 1 - -set -eo pipefail -SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) - -########################################################################### -# CONFIGURATION -########################################################################### -BUILD_PROJECT_FILE="$SCRIPT_DIR/build/build.csproj" -TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp" - -DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" -DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh" -DOTNET_CHANNEL="STS" - -export DOTNET_CLI_TELEMETRY_OPTOUT=1 -export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 -export DOTNET_MULTILEVEL_LOOKUP=0 - -########################################################################### -# EXECUTION -########################################################################### - -function FirstJsonValue { - perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}" -} - -# If dotnet CLI is installed globally and it matches requested version, use for execution -if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then - export DOTNET_EXE="$(command -v dotnet)" -else - # Download install script - DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh" - mkdir -p "$TEMP_DIRECTORY" - curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL" - chmod +x "$DOTNET_INSTALL_FILE" - - # If global.json exists, load expected version - if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then - DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")") - if [[ "$DOTNET_VERSION" == "" ]]; then - unset DOTNET_VERSION - fi - fi - - # Install by channel or version - DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix" - if [[ -z ${DOTNET_VERSION+x} ]]; then - "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path - else - "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path - fi - export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet" -fi - -echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)" - -if [[ ! -z ${NUKE_ENTERPRISE_TOKEN+x} && "$NUKE_ENTERPRISE_TOKEN" != "" ]]; then - "$DOTNET_EXE" nuget remove source "nuke-enterprise" &>/dev/null || true - "$DOTNET_EXE" nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password "$NUKE_ENTERPRISE_TOKEN" --store-password-in-clear-text &>/dev/null || true -fi - -"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet -"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@" diff --git a/build/.editorconfig b/build/.editorconfig deleted file mode 100644 index 31e43dc..0000000 --- a/build/.editorconfig +++ /dev/null @@ -1,11 +0,0 @@ -[*.cs] -dotnet_style_qualification_for_field = false:warning -dotnet_style_qualification_for_property = false:warning -dotnet_style_qualification_for_method = false:warning -dotnet_style_qualification_for_event = false:warning -dotnet_style_require_accessibility_modifiers = never:warning - -csharp_style_expression_bodied_methods = true:silent -csharp_style_expression_bodied_properties = true:warning -csharp_style_expression_bodied_indexers = true:warning -csharp_style_expression_bodied_accessors = true:warning diff --git a/build/Build.cs b/build/Build.cs deleted file mode 100644 index d78a3f3..0000000 --- a/build/Build.cs +++ /dev/null @@ -1,79 +0,0 @@ -using Nuke.Common; -using Nuke.Common.Git; -using Nuke.Common.IO; -using Nuke.Common.Tools.Docker; -using Nuke.Common.Tools.DotNet; -using Nuke.Common.Tools.SonarScanner; -using Serilog; - -class Build : NukeBuild -{ - /// Support plugins are available for: - /// - JetBrains ReSharper https://nuke.build/resharper - /// - JetBrains Rider https://nuke.build/rider - /// - Microsoft VisualStudio https://nuke.build/visualstudio - /// - Microsoft VSCode https://nuke.build/vscode - public static int Main() => Execute(x => x.Information, x => x.Deploy); - - [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] - readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release; - - GitRepository GitRepository => GitRepository.FromLocalDirectory(RootDirectory); - - Target Information => _ => _ - .Before(Clean) - .Executes(() => - { - Log.Information("Branch Name: {BranchName}", GitRepository.Branch); - Log.Information("Commit: {Commit}", GitRepository.Commit); - }); - - Target Clean => _ => _ - .Before(Restore) - .Executes(() => DotNetTasks.DotNetClean()); - - Target Restore => _ => _ - .Executes(() => DotNetTasks.DotNetRestore()); - - Target Compile => _ => _ - .DependsOn(Clean) - .DependsOn(Restore) - .Executes(() => - { - DockerTasks.DockerStackRm(settings => settings.SetStacks("continuity")); - DotNetTasks.DotNetBuild(settings => settings.SetNoRestore(true)); - }); - - Target Pack => _ => _ - .DependsOn(Compile) - .Executes(() => - { - DockerTasks.DockerBuild(settings => settings - .SetPath(AbsolutePath.Create(RootDirectory)) - .SetFile("Server/Dockerfile") - .SetTag("continuity-server:latest") - .SetCompress(true) - .SetProgress(ProgressType.auto)); - if (!IsLocalBuild) - { - DockerTasks.DockerPush(settings => settings.SetName("continuity-server:latest")); - } - }); - - Target Deploy => _ => _.DependsOn(Pack).Executes(() => - { - DockerTasks.DockerPull(settings => settings.SetName("postgres:16.0-alpine")); - if (IsLocalBuild) - { - var dockerComposeFile = AbsolutePath.Create(RootDirectory / "Server" / "docker-compose.yml"); - DockerTasks.DockerStackDeploy(settings => settings - .AddComposeFile(dockerComposeFile) - .SetStack("continuity") - .SetPrune(true) - ); - return; - } - - Log.Error("Deploy is only available on local builds."); - }); -} diff --git a/build/Configuration.cs b/build/Configuration.cs deleted file mode 100644 index 5519911..0000000 --- a/build/Configuration.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.ComponentModel; -using Nuke.Common.Tooling; - -[TypeConverter(typeof(TypeConverter))] -public class Configuration : Enumeration -{ - public static Configuration Debug { get; } = new() { Value = nameof(Debug) }; - public static Configuration Release { get; } = new() { Value = nameof(Release) }; - - public static implicit operator string(Configuration configuration) => configuration.Value; -} diff --git a/build/Directory.Build.props b/build/Directory.Build.props deleted file mode 100644 index e147d63..0000000 --- a/build/Directory.Build.props +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/build/Directory.Build.targets b/build/Directory.Build.targets deleted file mode 100644 index 2532609..0000000 --- a/build/Directory.Build.targets +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/build/build.csproj b/build/build.csproj deleted file mode 100644 index c97b50f..0000000 --- a/build/build.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - Exe - net6.0 - - CS0649;CS0169;CA1050;CA1822;CA2211;IDE1006 - .. - .. - 1 - false - - - - - - - diff --git a/build/build.csproj.DotSettings b/build/build.csproj.DotSettings deleted file mode 100644 index eb3f4c2..0000000 --- a/build/build.csproj.DotSettings +++ /dev/null @@ -1,28 +0,0 @@ - - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - Implicit - Implicit - ExpressionBody - 0 - NEXT_LINE - True - False - 120 - IF_OWNER_IS_SINGLE_LINE - WRAP_IF_LONG - False - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - True - True - True - True - True - True - True - True - True diff --git a/global.json b/global.json index c65c9ea..ad3eb2c 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "sdk": { - "version": "8.0.0", - "rollForward": "latestMinor", + "version": "7.0.403", + "rollForward": "latestMajor", "allowPrerelease": true } } \ No newline at end of file