From 9698b95968ab5a7dcd3b90165db5a2ab8990402d Mon Sep 17 00:00:00 2001 From: Kenichi Kamiya Date: Sun, 30 May 2021 02:03:31 +0900 Subject: [PATCH] Create template with importing my gems * https://github.com/kachick/ruby-ulid * https://github.com/kachick/rspec-matchers-power_assert_matchers The motivation is https://github.com/kachick/times_kachick/issues/75 --- .editorconfig | 9 + .github/dependabot.yml | 15 + .github/workflows/deploy_documents.yml | 28 + .github/workflows/lint.yml | 25 + .github/workflows/test_behaviors.yml | 51 ++ .github/workflows/test_signatures.yml | 40 ++ .gitignore | 28 + .rspec | 2 + .rubocop.yml | 906 +++++++++++++++++++++++++ .yardopts | 3 + CONTRIBUTING.md | 52 ++ Gemfile | 29 + MIT-LICENSE.txt | 21 + README.md | 40 ++ Rakefile | 53 ++ Steepfile | 9 + benchmark/example.rb | 11 + bin/console | 11 + bin/setup | 6 + lib/my_new_library.rb | 38 ++ lib/my_new_library/version.rb | 6 + logo.png | Bin 0 -> 47392 bytes my_new_library.gemspec | 63 ++ sig/my_new_library.rbs | 19 + spec/my_new_library_spec.rb | 11 + spec/spec_helper.rb | 35 + test/helper.rb | 38 ++ test/test_my_new_library.rb | 30 + 28 files changed, 1579 insertions(+) create mode 100644 .editorconfig create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/deploy_documents.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/test_behaviors.yml create mode 100644 .github/workflows/test_signatures.yml create mode 100644 .gitignore create mode 100644 .rspec create mode 100644 .rubocop.yml create mode 100644 .yardopts create mode 100644 CONTRIBUTING.md create mode 100644 Gemfile create mode 100644 MIT-LICENSE.txt create mode 100644 README.md create mode 100644 Rakefile create mode 100644 Steepfile create mode 100644 benchmark/example.rb create mode 100755 bin/console create mode 100755 bin/setup create mode 100644 lib/my_new_library.rb create mode 100644 lib/my_new_library/version.rb create mode 100644 logo.png create mode 100644 my_new_library.gemspec create mode 100644 sig/my_new_library.rbs create mode 100644 spec/my_new_library_spec.rb create mode 100644 spec/spec_helper.rb create mode 100644 test/helper.rb create mode 100644 test/test_my_new_library.rb diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0ed8036 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +end_of_line = lf +charset = utf-8 +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..88ca166 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + time: "08:00" + timezone: "Asia/Tokyo" + - package-ecosystem: "bundler" + directory: "/" + schedule: + interval: "daily" + time: "08:00" + timezone: "Asia/Tokyo" + versioning-strategy: increase diff --git a/.github/workflows/deploy_documents.yml b/.github/workflows/deploy_documents.yml new file mode 100644 index 0000000..4bbb509 --- /dev/null +++ b/.github/workflows/deploy_documents.yml @@ -0,0 +1,28 @@ +name: Deploy documents +on: + push: + branches: [ main ] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.0' + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + - name: git setting + run: | + git config --local user.email "kachick1@gmail.com" + git config --local user.name "Kenichi Kamiya" + - name: Update YARD documents and deploy to GitHub Pages + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + DATE=`date +"%Y%m%d-%H%M-UTC"` + BRANCH_NAME="documents-$DATE" + git checkout -b "$BRANCH_NAME" + bundle exec yard --output-dir docs + git add docs + git commit -m 'Update YARD documents' docs + git push origin "$BRANCH_NAME":gh-pages --force diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..5fcac82 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,25 @@ +# https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions +name: Lint +on: + push: + branches: + - main + paths-ignore: + - 'docs/**' + pull_request: null # This enables to run on each PRs +jobs: + rubocop: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0' + ruby: ['3.0'] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + - run: bundle exec rake rubocop diff --git a/.github/workflows/test_behaviors.yml b/.github/workflows/test_behaviors.yml new file mode 100644 index 0000000..4b8d87b --- /dev/null +++ b/.github/workflows/test_behaviors.yml @@ -0,0 +1,51 @@ +# https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions +name: Test +on: + push: + branches: + - main + paths-ignore: + - 'docs/**' + - 'benchmark/**' + - 'bin/**' + - 'scripts/**' + - 'sig/**' + - 'Steepfile' + - '**.md' + - '*LICENSE*' + - 'logo.png' + - '.yardopts' + - '.editorconfig' + - '.rubocop.yml' + pull_request: + paths-ignore: + - 'docs/**' + - 'benchmark/**' + - 'bin/**' + - 'scripts/**' + - 'sig/**' + - 'Steepfile' + - '**.md' + - '*LICENSE*' + - 'logo.png' + - '.yardopts' + - '.editorconfig' + - '.rubocop.yml' +jobs: + test_behaviors: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0' + ruby: [2.5, 2.6, 2.7, '3.0', head] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - uses: ruby/setup-ruby@v1 + env: + BUNDLE_WITHOUT: development + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + - run: bundle exec rake test_behaviors diff --git a/.github/workflows/test_signatures.yml b/.github/workflows/test_signatures.yml new file mode 100644 index 0000000..20ae562 --- /dev/null +++ b/.github/workflows/test_signatures.yml @@ -0,0 +1,40 @@ +name: Signature - rbs & YARD +on: + push: + branches: + - main + paths-ignore: + - 'docs/**' + - 'benchmark/**' + - 'bin/**' + - 'scripts/**' + - 'test/**' + - 'spec/**' + - 'logo.png' + - '.rubocop.yml' + pull_request: + paths-ignore: + - 'docs/**' + - 'benchmark/**' + - 'bin/**' + - 'scripts/**' + - 'test/**' + - 'spec/**' + - 'logo.png' + - '.rubocop.yml' +jobs: + validate_signatures: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0' + ruby: ['3.0'] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + - run: bundle exec rake validate_signatures diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7ea6b55 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +/coverage/ +/pkg/ +/spec/reports/ +/test/tmp/ +/tmp/ + +.rspec_status + +# Used by dotenv library to load environment variables. +.env +.env.production + +# Ignore Byebug command history file. +.byebug_history + +## Documentation cache and generated files: +/.yardoc/ +/_yardoc/ +/doc/ +/rdoc/ + +## Environment normalization: +/.bundle/ +/vendor/ + +*.lock + +.DS_Store diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..83e16f8 --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--color +--require spec_helper diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..3f93b27 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,906 @@ +require: + - rubocop-rake + - rubocop-performance + - rubocop-rubycw + - rubocop-rspec + - rubocop-md + +AllCops: + TargetRubyVersion: 2.5 + DisplayCopNames: true + Exclude: + - '**/vendor/**/*' + - 'pkg/**/*' + NewCops: enable + +Metrics: + Enabled: false + +Naming: + Enabled: false + +Layout: + Enabled: true + Include: + - 'lib/**/*' + +Migration: + Enabled: true + +Security: + Enabled: true + +Lint: + Enabled: true + +Style: + Enabled: true + +Bundler: + Enabled: true + +Rake: + Enabled: true + +Rake/Desc: + Enabled: false + +Gemspec: + Enabled: true + +Performance: + Enabled: true + Include: + - 'lib/**/*' + +Style/Alias: + Enabled: false + +Style/HashSyntax: + Enabled: true + EnforcedStyle: 'ruby19' + +Style/TrailingMethodEndStatement: + Enabled: true + +Style/MethodDefParentheses: + Enabled: true + EnforcedStyle: 'require_parentheses' + +Style/TrailingCommaInBlockArgs: + Enabled: true + +Style/StringLiterals: + Enabled: true + EnforcedStyle: 'single_quotes' + +Style/StringLiteralsInInterpolation: + Enabled: true + EnforcedStyle: 'single_quotes' + +Style/TopLevelMethodDefinition: + Enabled: true + +Style/AndOr: + Enabled: true + +Style/ArgumentsForwarding: + Enabled: true + +Style/ArrayCoercion: + Enabled: false + +Style/ArrayJoin: + Enabled: true + +Style/AsciiComments: + Enabled: false + +Style/Attr: + Enabled: true + +Style/AutoResourceCleanup: + Enabled: true + +Style/BarePercentLiterals: + Enabled: true + EnforcedStyle: 'percent_q' + +Style/BeginBlock: + Enabled: true + +Style/BisectedAttrAccessor: + Enabled: true + +Style/BlockComments: + Enabled: false + +Style/BlockDelimiters: + Enabled: false + +Style/CaseEquality: + Enabled: false + +Style/CaseLikeIf: + Enabled: true + +Style/CharacterLiteral: + Enabled: false + +Style/ClassAndModuleChildren: + Enabled: true + EnforcedStyle: 'nested' + Exclude: + - 'test/**/*' + +Style/ClassCheck: + Enabled: true + EnforcedStyle: 'kind_of?' + +Style/ClassEqualityComparison: + Enabled: false + +Style/ClassMethods: + Enabled: true + +Style/ClassMethodsDefinitions: + Enabled: false + +Style/ClassVars: + Enabled: true + +Style/CollectionCompact: + Enabled: false + +Style/CollectionMethods: + Enabled: false + +Style/ColonMethodCall: + Enabled: true + +Style/ColonMethodDefinition: + Enabled: true + +Style/CombinableLoops: + Enabled: false + +Style/CommandLiteral: + Enabled: false + +Style/CommentAnnotation: + Enabled: true + +Style/CommentedKeyword: + Enabled: true + +Style/ConditionalAssignment: + Enabled: true + EnforcedStyle: 'assign_to_condition' + +Style/ConstantVisibility: + Enabled: false + +Style/Copyright: + Enabled: false + +Style/DateTime: + Enabled: true + +Style/DefWithParentheses: + Enabled: true + +Style/Dir: + Enabled: true + +Style/DisableCopsWithinSourceCodeDirective: + Enabled: true + +Style/DocumentDynamicEvalDefinition: + Enabled: false + +Style/Documentation: + Enabled: false + +Style/DocumentationMethod: + Enabled: false + +Style/DoubleCopDisableDirective: + Enabled: false + +Style/DoubleNegation: + Enabled: false + +Style/EachForSimpleLoop: + Enabled: true + +Style/EachWithObject: + Enabled: true + +Style/EmptyBlockParameter: + Enabled: true + +Style/EmptyCaseCondition: + Enabled: false + +Style/EmptyElse: + Enabled: true + EnforcedStyle: 'empty' + +Style/EmptyLambdaParameter: + Enabled: false + +Style/EmptyLiteral: + Enabled: true + +Style/EmptyMethod: + Enabled: true + EnforcedStyle: 'compact' + +Style/Encoding: + Enabled: false + +Style/EndBlock: + Enabled: true + +Style/EndlessMethod: + Enabled: true + EnforcedStyle: 'allow_always' + +Style/EvalWithLocation: + Enabled: true + +Style/EvenOdd: + Enabled: true + +Style/ExpandPathArguments: + Enabled: true + +Style/ExplicitBlockArgument: + Enabled: false + +Style/ExponentialNotation: + Enabled: false + +Style/FloatDivision: + Enabled: true + EnforcedStyle: 'fdiv' + +Style/For: + Enabled: true + EnforcedStyle: 'each' + +Style/FormatString: + Enabled: false + +Style/FormatStringToken: + Enabled: false + +Style/FrozenStringLiteralComment: + Enabled: true + EnforcedStyle: 'always' + +Style/GlobalStdStream: + Enabled: false + +Style/GlobalVars: + Enabled: true + +Style/GuardClause: + Enabled: false + +Style/HashAsLastArrayItem: + Enabled: true + EnforcedStyle: 'braces' + +Style/HashConversion: + Enabled: true + AllowSplatArgument: true + +Style/HashEachMethods: + Enabled: true + +Style/HashExcept: + Enabled: true + +Style/HashLikeCase: + Enabled: false + +Style/HashTransformKeys: + Enabled: true + +Style/HashTransformValues: + Enabled: true + +Style/IdenticalConditionalBranches: + Enabled: false + +Style/IfInsideElse: + Enabled: false + +Style/IfUnlessModifier: + Enabled: false + +Style/IfUnlessModifierOfIfUnless: + Enabled: true + +Style/IfWithBooleanLiteralBranches: + Enabled: true + +Style/IfWithSemicolon: + Enabled: true + +Style/ImplicitRuntimeError: + Enabled: false + +Style/InfiniteLoop: + Enabled: true + +Style/InlineComment: + Enabled: false + +Style/InverseMethods: + Enabled: false + +Style/IpAddresses: + Enabled: false + +Style/KeywordParametersOrder: + Enabled: false + +Style/Lambda: + Enabled: true + EnforcedStyle: 'literal' + +Style/LambdaCall: + Enabled: false + +Style/LineEndConcatenation: + Enabled: false + +Style/MethodCallWithArgsParentheses: + Enabled: true + EnforcedStyle: 'require_parentheses' + IgnoreMacros: true + AllowParenthesesInMultilineCall: false + AllowParenthesesInChaining: true + AllowParenthesesInCamelCaseMethod: true + AllowParenthesesInStringInterpolation: true + IgnoredMethods: ['raise', 'puts', 'yield', 'require', 'require_relative', 'load', 'to', 'describe', 'context'] + Exclude: + - '*.gemspec' + +Style/MethodCallWithoutArgsParentheses: + Enabled: true + +Style/MethodCalledOnDoEndBlock: + Enabled: false + +Style/MinMax: + Enabled: false + +Style/MissingElse: + Enabled: false + +Style/MissingRespondToMissing: + Enabled: true + +Style/MixinGrouping: + Enabled: false + +Style/MixinUsage: + Enabled: true + +Style/ModuleFunction: + Enabled: false + +Style/MultilineBlockChain: + Enabled: false + +Style/MultilineIfModifier: + Enabled: false + +Style/MultilineIfThen: + Enabled: true + +Style/MultilineMemoization: + Enabled: false + +Style/MultilineMethodSignature: + Enabled: true + +Style/MultilineTernaryOperator: + Enabled: true + +Style/MultilineWhenThen: + Enabled: true + +Style/MultipleComparison: + Enabled: false + +Style/MutableConstant: + Enabled: true + EnforcedStyle: 'literals' + +Style/NegatedIf: + Enabled: false + +Style/NegatedIfElseCondition: + Enabled: false + +Style/NegatedUnless: + Enabled: true + EnforcedStyle: 'both' + +Style/NegatedWhile: + Enabled: true + +Style/NestedModifier: + Enabled: true + +Style/NestedParenthesizedCalls: + Enabled: true + +Style/NestedTernaryOperator: + Enabled: false + +Style/Next: + Enabled: false + +Style/NilComparison: + Enabled: false + +Style/NilLambda: + Enabled: false + +Style/NonNilCheck: + Enabled: false + +Style/Not: + Enabled: true + +Style/NumericLiteralPrefix: + Enabled: true + EnforcedOctalStyle: 'zero_with_o' + +Style/NumericLiterals: + Enabled: false + +Style/NumericPredicate: + Enabled: false + +Style/OneLineConditional: + Enabled: true + +Style/OptionHash: + Enabled: true + +Style/OptionalArguments: + Enabled: true + +Style/OptionalBooleanParameter: + Enabled: true + +Style/OrAssignment: + Enabled: true + +Style/ParallelAssignment: + Enabled: false + +Style/ParenthesesAroundCondition: + Enabled: false + +Style/PercentLiteralDelimiters: + Enabled: false + +Style/PercentQLiterals: + Enabled: true + EnforcedStyle: 'lower_case_q' + +Style/PerlBackrefs: + Enabled: true + +Style/PreferredHashMethods: + Enabled: true + EnforcedStyle: 'short' + +Style/Proc: + Enabled: false + +Style/RaiseArgs: + Enabled: false + +Style/RandomWithOffset: + Enabled: true + +Style/RedundantArgument: + Enabled: true + +Style/RedundantAssignment: + Enabled: true + +Style/RedundantBegin: + Enabled: false + +Style/RedundantCapitalW: + Enabled: true + +Style/RedundantCondition: + Enabled: true + +Style/RedundantConditional: + Enabled: true + +Style/RedundantException: + Enabled: false + +Style/RedundantFetchBlock: + Enabled: true + +Style/RedundantFileExtensionInRequire: + Enabled: true + +Style/RedundantFreeze: + Enabled: false + +Style/RedundantInterpolation: + Enabled: true + +Style/RedundantParentheses: + Enabled: true + +Style/RedundantPercentQ: + Enabled: false + +Style/RedundantRegexpCharacterClass: + Enabled: true + +Style/RedundantRegexpEscape: + Enabled: true + +Style/RedundantReturn: + Enabled: true + AllowMultipleReturnValues: true + +Style/RedundantSelf: + Enabled: true + +Style/RedundantSelfAssignment: + Enabled: true + +Style/RedundantSort: + Enabled: true + +Style/RedundantSortBy: + Enabled: true + +Style/RegexpLiteral: + Enabled: false + +Style/RescueModifier: + Enabled: true + +Style/RescueStandardError: + Enabled: true + EnforcedStyle: 'implicit' + +Style/ReturnNil: + Enabled: false + +Style/SafeNavigation: + Enabled: false + +Style/Sample: + Enabled: true + +Style/SelfAssignment: + Enabled: false + +Style/Semicolon: + Enabled: true + AllowAsExpressionSeparator: true + +Style/Send: + Enabled: true + +Style/SignalException: + Enabled: false + +Style/SingleArgumentDig: + Enabled: true + +Style/SingleLineBlockParams: + Enabled: false + +Style/SingleLineMethods: + Enabled: false + +Style/SlicingWithRange: + Enabled: true + +Style/SoleNestedConditional: + Enabled: false + +Style/SpecialGlobalVars: + Enabled: true + EnforcedStyle: 'use_english_names' + +Style/StabbyLambdaParentheses: + Enabled: false + +Style/StaticClass: + Enabled: false + +Style/StderrPuts: + Enabled: false + +Style/StringChars: + Enabled: true + +Style/StringConcatenation: + Enabled: false + +Style/StringHashKeys: + Enabled: false + +Style/StringMethods: + Enabled: false + +Style/Strip: + Enabled: true + +Style/StructInheritance: + Enabled: true + +Style/SwapValues: + Enabled: false + +Style/SymbolArray: + Enabled: false + +Style/SymbolLiteral: + Enabled: true + +Style/SymbolProc: + Enabled: true + +Style/TernaryParentheses: + Enabled: true + EnforcedStyle: 'require_parentheses_when_complex' + +Style/TrailingBodyOnClass: + Enabled: true + +Style/TrailingBodyOnMethodDefinition: + Enabled: true + +Style/TrailingBodyOnModule: + Enabled: true + +Style/TrailingCommaInArguments: + Enabled: true + EnforcedStyleForMultiline: 'no_comma' + +Style/TrailingCommaInArrayLiteral: + Enabled: true + EnforcedStyleForMultiline: 'no_comma' + +Style/TrailingCommaInHashLiteral: + Enabled: true + EnforcedStyleForMultiline: 'no_comma' + +Style/TrailingUnderscoreVariable: + Enabled: true + AllowNamedUnderscoreVariables: true + +Style/TrivialAccessors: + Enabled: true + ExactNameMatch: true + AllowPredicates: true + AllowDSLWriters: true + IgnoreClassMethods: false + +Style/UnlessElse: + Enabled: true + +Style/UnlessLogicalOperators: + Enabled: false + +Style/UnpackFirst: + Enabled: true + +Style/VariableInterpolation: + Enabled: false + +Style/WhenThen: + Enabled: true + +Style/WhileUntilDo: + Enabled: true + +Style/WhileUntilModifier: + Enabled: false + +Style/WordArray: + Enabled: false + +Style/YodaCondition: + Enabled: false + +Style/ZeroLengthPredicate: + Enabled: true + +Layout/TrailingEmptyLines: + Enabled: true + +Layout/TrailingWhitespace: + Enabled: true + +Layout/SpaceBeforeFirstArg: + Enabled: true + +Layout/SpaceBeforeSemicolon: + Enabled: true + +Layout/SpaceInsideArrayPercentLiteral: + Enabled: true + +Layout/SpaceInsideBlockBraces: + Enabled: true + +Layout/SpaceInsideParens: + Enabled: true + +Layout/SpaceInsidePercentLiteralDelimiters: + Enabled: true + +Layout/SpaceInsideRangeLiteral: + Enabled: true + +Layout/SpaceInsideReferenceBrackets: + Enabled: true + +Layout/SpaceInsideStringInterpolation: + Enabled: true + +Layout/SpaceAroundMethodCallOperator: + Enabled: true + +Layout/LineLength: + Enabled: false + +Layout/SpaceAroundOperators: + Enabled: true + EnforcedStyleForExponentOperator: 'space' + +Layout/MultilineMethodCallBraceLayout: + Enabled: false + +Layout/SpaceInsideHashLiteralBraces: + Enabled: true + +Layout/EmptyLineBetweenDefs: + Enabled: true + AllowAdjacentOneLineDefs: true + +Layout/SpaceAroundEqualsInParameterDefault: + Enabled: true + EnforcedStyle: 'no_space' + +Naming/MethodName: + Enabled: true + EnforcedStyle: 'snake_case' + +Naming/FileName: + Enabled: true + +Naming/ConstantName: + Enabled: true + +Naming/ClassAndModuleCamelCase: + Enabled: true + +Naming/BlockParameterName: + Enabled: true + +Naming/HeredocDelimiterCase: + Enabled: true + +Naming/HeredocDelimiterNaming: + Enabled: true + +Naming/MemoizedInstanceVariableName: + Enabled: false + +Naming/MethodParameterName: + Enabled: false + +Naming/PredicateName: + Enabled: true + +Naming/RescuedExceptionsVariableName: + Enabled: false + +Naming/VariableName: + Enabled: true + EnforcedStyle: 'snake_case' + +Naming/VariableNumber: + Enabled: false + +Bundler/OrderedGems: + Enabled: false + +Gemspec/OrderedDependencies: + Enabled: false + +Lint/AmbiguousAssignment: + Enabled: true + +Lint/AmbiguousBlockAssociation: + Enabled: true + +Lint/AmbiguousOperator: + Enabled: true + +Lint/AmbiguousRegexpLiteral: + Enabled: true + +Lint/InheritException: + Enabled: false + +Lint/RedundantStringCoercion: + Enabled: false + +Lint/StructNewOverride: + Exclude: + - 'test/many_data/fixtures/example.rb' + +Lint/BinaryOperatorWithIdenticalOperands: + Exclude: + - 'test/**/*' + +Lint/UnusedMethodArgument: + Enabled: false + +Lint/AssignmentInCondition: + Enabled: false + +Lint/RescueException: + Enabled: false + +Lint/DuplicateMethods: + Enabled: true + +Lint/BigDecimalNew: + Enabled: true + +Lint/BooleanSymbol: + Enabled: false + +Lint/CircularArgumentReference: + Enabled: true + +Lint/ConstantDefinitionInBlock: + Enabled: true + +Lint/ConstantResolution: + Enabled: false + +Rubycw/Rubycw: + Enabled: true + Include: + - '**/*.rb' + - 'Rakefile' + - 'Steepfile' + - 'bin/**/*' + - 'exe/**/*' + +RSpec/MultipleExpectations: + Enabled: false + +RSpec/DescribedClass: + Enabled: false + +Markdown: + WarnInvalid: true + Autodetect: true diff --git a/.yardopts b/.yardopts new file mode 100644 index 0000000..e347a58 --- /dev/null +++ b/.yardopts @@ -0,0 +1,3 @@ +--fail-on-warning +- +MIT-LICENSE.txt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6261e6a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,52 @@ +# How to contribute + +* Reporting bugs +* Suggesting features +* Creating PRs + +Welcome all of the contributions! + +## Development + +At first, you should install development dependencies + +```console +$ git clone git@github.com:kachick/my_new_library.git +$ cd ./my_new_library +$ ./bin/setup +# Executing first time might take longtime, because development mode dependent active_support via steep +``` + +## Feel the latest version with REPL + +```console +$ ./bin/console +Starting up IRB with loading developing this library +``` + +## How to make ideal PRs (Not a mandatory rule, feel free to PR!) + +If you try to add/change/fix features, please update and/or confirm core feature's tests are not broken. + +```console +$ bundle exec rake +$ echo $? +0 +``` + +If you want to run partially tests, test-unit can take some patterns(String/Regexp) with the naming. + +```console +$ bundle exec rake test TESTOPTS="-v -n'/test_.*foobar/i'" +Runs test cases only for matched the pattern +``` + +CI includes signature check, lint, if you want to check them in own machine, below command is the one. + +But please don't hesitate to send PRs even if something fail in this command! + +```console +$ bundle exec rake simulate_ci +$ echo $? +0 +``` diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..2198b9d --- /dev/null +++ b/Gemfile @@ -0,0 +1,29 @@ +# coding: us-ascii +# frozen_string_literal: true + +source 'https://rubygems.org' + +gemspec + +group :development, :test do + gem 'rake' + gem 'irb' + gem 'irb-power_assert' +end + +group :development do + gem 'steep', require: false + gem 'rubocop', require: false + gem 'rubocop-rake', require: false + gem 'rubocop-performance', require: false + gem 'rubocop-rubycw', require: false + gem 'rubocop-rspec', require: false + gem 'rubocop-md', require: false +end + +group :test do + gem 'test-unit' + gem 'rspec' + gem 'rspec-matchers-power_assert_matchers' + gem 'warning' +end diff --git a/MIT-LICENSE.txt b/MIT-LICENSE.txt new file mode 100644 index 0000000..288da25 --- /dev/null +++ b/MIT-LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Kenichi Kamiya + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..0026479 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# my_new_library + +Ruby library template for [@kachick](https://github.com/kachick), To make easy to create own gem that having prepared environment + +The motivation is [written in Japanese](https://github.com/kachick/times_kachick/issues/75) + +## Overview + +![logo](https://raw.githubusercontent.com/kachick/my_new_library/main/logo.png) + +![Build Status](https://github.com/kachick/my_new_library/actions/workflows/test_behaviors.yml/badge.svg?branch=main) +[![Gem Version](https://badge.fury.io/rb/my_new_library.png)](http://badge.fury.io/rb/my_new_library) + +## Usage + +### Install + +Require Ruby 2.5 or later + +This command will install the latest version into your environment + +```console +$ gem install my_new_library +Should be installed! +``` + +Add this line to your application/library's `Gemfile` is needed in basic use-case + +```ruby +gem 'my_new_library', '>= 0.0.1', '< 0.1.0' +``` + +## References + +- [Repository](https://github.com/kachick/my_new_library) +- [API documents](https://kachick.github.io/my_new_library/) + +## Note + +:) diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..7d9cb06 --- /dev/null +++ b/Rakefile @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'bundler/gem_tasks' + +require 'rake/testtask' +require 'rspec/core/rake_task' + +begin + require 'rubocop/rake_task' +rescue LoadError + puts 'can not use rubocop in this environment' +else + RuboCop::RakeTask.new +end + +task default: [:test_behaviors] +task test_behaviors: [:test, :spec] + +multitask simulate_ci: [:test_behaviors, :validate_signatures, :rubocop] + +Rake::TestTask.new(:test) do |tt| + tt.pattern = 'test/**/test_*.rb' + tt.verbose = true + tt.warning = true +end + +RSpec::Core::RakeTask.new(:spec) do |rt| + rt.ruby_opts = %w[-w] +end + +task validate_signatures: [:test_yard, :'signature:validate'] + +namespace :signature do + task :validate do + sh 'bundle exec rbs -rsecurerandom -rmonitor -I sig validate' + end + + task :check_false_positive do + sh 'bundle exec steep check --log-level=fatal' + end +end + +task :test_yard do + sh "bundle exec yard --fail-on-warning #{'--no-progress' if ENV['CI']}" +end + +task :yard do + sh 'bundle exec yard --fail-on-warning' +end + +task :benchmark do + sh 'bundle exec ruby ./benchmark/example.rb' +end diff --git a/Steepfile b/Steepfile new file mode 100644 index 0000000..b512e95 --- /dev/null +++ b/Steepfile @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +target :lib do + signature 'sig' + + check 'lib' + + library 'securerandom', 'monitor' +end diff --git a/benchmark/example.rb b/benchmark/example.rb new file mode 100644 index 0000000..126678b --- /dev/null +++ b/benchmark/example.rb @@ -0,0 +1,11 @@ +# coding: utf-8 +# frozen_string_literal: true + +require 'benchmark/ips' +require_relative '../lib/my_new_library' + +Benchmark.ips do |x| + x.report('MyNewLibrary.something') { MyNewLibrary.something } + x.report('MyNewLibrary.something') { MyNewLibrary.something } + x.compare! +end diff --git a/bin/console b/bin/console new file mode 100755 index 0000000..ca01a33 --- /dev/null +++ b/bin/console @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'bundler/setup' +require 'irb' +require 'irb/completion' +require 'irb/power_assert' + +require_relative '../lib/my_new_library' + +IRB.start diff --git a/bin/setup b/bin/setup new file mode 100755 index 0000000..cf4ad25 --- /dev/null +++ b/bin/setup @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -euo pipefail +IFS=$'\n\t' +set -vx + +bundle install diff --git a/lib/my_new_library.rb b/lib/my_new_library.rb new file mode 100644 index 0000000..d98972b --- /dev/null +++ b/lib/my_new_library.rb @@ -0,0 +1,38 @@ +# coding: us-ascii +# frozen_string_literal: true + +# Copyright (C) 2021 Kenichi Kamiya + +# require 'securerandom' + +# @!attribute [r] milliseconds +# @return [Integer] +class MyNewLibrary + class Error < StandardError; end + class UnexpectedError < Error; end + + FOOBAR = 42 + + attr_reader :milliseconds + + # @api private + # @param [Integer] milliseconds + # @param [Integer] integer + # @return [void] + def initialize(milliseconds:, integer:) + # All arguments check should be done with each constructors, not here + @integer = integer + @milliseconds = milliseconds + end + + # @return [String] + def inspect + ':)' + end +end + +require_relative 'my_new_library/version' + +class MyNewLibrary + private_constant :FOOBAR +end diff --git a/lib/my_new_library/version.rb b/lib/my_new_library/version.rb new file mode 100644 index 0000000..b146e87 --- /dev/null +++ b/lib/my_new_library/version.rb @@ -0,0 +1,6 @@ +# coding: us-ascii +# frozen_string_literal: true + +class MyNewLibrary + VERSION = '0.0.1' +end diff --git a/logo.png b/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ed579f35daa5253ea1e1596dae608dd92c425f96 GIT binary patch literal 47392 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 'https://kachick.github.io/my_new_library/', + 'homepage_uri' => repository_url, + 'source_code_uri' => repository_url, + 'bug_tracker_uri' => "#{repository_url}/issues" + } + + gem.add_development_dependency 'test-unit', '>= 3.4.1', '< 4.0' + gem.add_development_dependency 'irb', '>= 1.3.5', '< 2.0' + gem.add_development_dependency 'irb-power_assert', '0.0.2' + gem.add_development_dependency 'rspec', '>= 3.10.0', '< 4.0' + gem.add_development_dependency 'rspec-matchers-power_assert_matchers', '0.0.2' + gem.add_development_dependency 'warning', '>= 1.2.0', '< 2.0' + gem.add_development_dependency 'rbs', '>= 1.2.0', '< 2.0' + gem.add_development_dependency 'rake', '>= 13.0.3', '< 20.0' + gem.add_development_dependency 'benchmark-ips', '>= 2.9.1', '< 3' + gem.add_development_dependency 'yard', '>= 0.9.26', '< 2' + gem.add_development_dependency 'steep', '>= 0.44.1', '< 0.50.0' + gem.add_development_dependency 'rubocop', '>= 1.15.0', '< 1.16.0' + gem.add_development_dependency 'rubocop-rake', '>= 0.5.1', '< 0.6.0' + gem.add_development_dependency 'rubocop-performance', '>= 1.11.3', '< 1.12.0' + gem.add_development_dependency 'rubocop-rubycw', '>= 0.1.6', '< 0.2.0' + gem.add_development_dependency 'rubocop-rspec', '>= 2.3.0', '< 3.0.0' + gem.add_development_dependency 'rubocop-md', '>= 1.0.1', '< 2.0.0' + + gem.required_ruby_version = Gem::Requirement.new('>= 2.5.0') + + # common + + gem.authors = ['Kenichi Kamiya'] + gem.email = ['kachick1+ruby@gmail.com'] + git_managed_files = `git ls-files`.lines.map(&:chomp) + might_be_parsing_by_tool_as_dependabot = git_managed_files.empty? + base_files = Dir['README*', '*LICENSE*', 'lib/**/*', 'sig/**/*'].uniq + files = might_be_parsing_by_tool_as_dependabot ? base_files : (base_files & git_managed_files) + + unless might_be_parsing_by_tool_as_dependabot + if files.grep(%r!\A(?:lib|sig)/!).size < 2 + raise "obvious mistaken in packaging files, looks shortage: #{files.inspect}" + end + end + + gem.files = files + gem.require_paths = ['lib'] +end diff --git a/sig/my_new_library.rbs b/sig/my_new_library.rbs new file mode 100644 index 0000000..5796d19 --- /dev/null +++ b/sig/my_new_library.rbs @@ -0,0 +1,19 @@ +class MyNewLibrary < Object + @integer: Integer? + + attr_reader milliseconds: Integer + + # ```ruby + # something = MyNewLibrary.neew + # something.inspect #=> ":)" + # ``` + def inspect: -> String + + private + + # A pribate API. Should not be used in your code. + def self.new: (milliseconds: Integer, integer: Integer) -> MyNewLibrary + + # A pribate API. Should not be used in your code. + def initialize: (milliseconds: Integer, integer: Integer) -> void +end diff --git a/spec/my_new_library_spec.rb b/spec/my_new_library_spec.rb new file mode 100644 index 0000000..691c889 --- /dev/null +++ b/spec/my_new_library_spec.rb @@ -0,0 +1,11 @@ +# coding: utf-8 +# frozen_string_literal: true + +RSpec.describe MyNewLibrary do + describe MyNewLibrary::VERSION do + it do + expect(MyNewLibrary::VERSION.frozen?).to eq(true) + expect(Gem::Version.correct?(MyNewLibrary::VERSION)).to eq(true) + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..ca2d1c9 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,35 @@ +# coding: us-ascii +# frozen_string_literal: true + +require 'rspec' +require 'rspec/matchers/power_assert_matchers' + +RSpec.configure do |config| + config.disable_monkey_patching! + config.warnings = true + config.raise_on_warning = true + + config.expect_with(:rspec) do |c| + c.syntax = :expect + end + + # Enable flags like --only-failures and --next-failure + config.example_status_persistence_file_path = '.rspec_status' +end + +require 'warning' + +if Warning.respond_to?(:[]=) # @TODO Removable this guard after dropped ruby 2.6 + Warning[:deprecated] = true + Warning[:experimental] = true +end + +Gem.path.each do |path| + Warning.ignore(//, path) +end + +Warning.process do |_warning| + :raise +end + +require_relative '../lib/my_new_library' diff --git a/test/helper.rb b/test/helper.rb new file mode 100644 index 0000000..dc35f17 --- /dev/null +++ b/test/helper.rb @@ -0,0 +1,38 @@ +# coding: us-ascii +# frozen_string_literal: true + +require 'warning' + +# How to use => https://test-unit.github.io/test-unit/en/ +require 'test/unit' + +require 'irb' +require 'power_assert/colorize' +require 'irb/power_assert' + +if Warning.respond_to?(:[]=) # @TODO Removable this guard after dropped ruby 2.6 + Warning[:deprecated] = true + Warning[:experimental] = true +end + +Warning.process do |_warning| + :raise +end + +require_relative '../lib/my_new_library' + +class Test::Unit::TestCase + module MyNewLibraryHelpers + def awesome_helper + nil + end + end + + module MyNewLibraryAssertions + def assert_awesome(object) + assert do + 'foo'.instance_of?(String) + end + end + end +end diff --git a/test/test_my_new_library.rb b/test/test_my_new_library.rb new file mode 100644 index 0000000..214f8d0 --- /dev/null +++ b/test/test_my_new_library.rb @@ -0,0 +1,30 @@ +# coding: utf-8 +# frozen_string_literal: true + +require_relative 'helper' + +class TestMyNewLibrary < Test::Unit::TestCase + include MyNewLibraryAssertions + + def setup + nil + end + + def test_constant_version + assert do + MyNewLibrary::VERSION.instance_of?(String) + end + + assert do + MyNewLibrary::VERSION.frozen? + end + + assert do + Gem::Version.correct?(MyNewLibrary::VERSION) + end + end + + def teardown + nil + end +end