diff --git a/.credo.exs b/.credo.exs index 919ff41..522b36a 100644 --- a/.credo.exs +++ b/.credo.exs @@ -1,3 +1,5 @@ +# This file is synced with beam-community/common-config. Any changes will be overwritten. + # This file contains the configuration for Credo and you are probably reading # this after creating it with `mix credo.gen.config`. # @@ -21,16 +23,7 @@ # You can give explicit globs or simply directories. # In the latter case `**/*.{ex,exs}` will be used. # - included: [ - "lib/", - "src/", - "test/", - "web/", - "apps/*/lib/", - "apps/*/src/", - "apps/*/test/", - "apps/*/web/" - ], + included: ["config/", "lib/", "priv/", "test/"], excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"] }, # @@ -46,7 +39,7 @@ # If you want to enforce a style guide and need a more traditional linting # experience, you can change `strict` to `true` below: # - strict: false, + strict: true, # # To modify the timeout for parsing files, change this value: # @@ -70,10 +63,12 @@ # {Credo.Check.Consistency.ExceptionNames, []}, {Credo.Check.Consistency.LineEndings, []}, + {Credo.Check.Consistency.MultiAliasImportRequireUse, []}, {Credo.Check.Consistency.ParameterPatternMatching, []}, {Credo.Check.Consistency.SpaceAroundOperators, []}, {Credo.Check.Consistency.SpaceInParentheses, []}, {Credo.Check.Consistency.TabsOrSpaces, []}, + {Credo.Check.Consistency.UnusedVariableNames, false}, # ## Design Checks @@ -81,7 +76,8 @@ # You can customize the priority of any check # Priority values are: `low, normal, high, higher` # - {Credo.Check.Design.AliasUsage, [priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 0]}, + {Credo.Check.Design.AliasUsage, [priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 2]}, + {Credo.Check.Design.DuplicatedCode, false}, # You can also customize the exit_status of each check. # If you don't want TODO comments to cause `mix credo` to fail, just # set this value to 0 (zero). @@ -92,53 +88,84 @@ # ## Readability Checks # + {Credo.Check.Readability.AliasAs, false}, {Credo.Check.Readability.AliasOrder, []}, + {Credo.Check.Readability.BlockPipe, []}, {Credo.Check.Readability.FunctionNames, []}, - {Credo.Check.Readability.LargeNumbers, []}, - {Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]}, + {Credo.Check.Readability.ImplTrue, []}, + {Credo.Check.Readability.LargeNumbers, [trailing_digits: 2]}, + {Credo.Check.Readability.MaxLineLength, false}, {Credo.Check.Readability.ModuleAttributeNames, []}, {Credo.Check.Readability.ModuleDoc, false}, {Credo.Check.Readability.ModuleNames, []}, + {Credo.Check.Readability.MultiAlias, false}, + {Credo.Check.Readability.NestedFunctionCalls, []}, {Credo.Check.Readability.ParenthesesInCondition, []}, {Credo.Check.Readability.ParenthesesOnZeroArityDefs, []}, {Credo.Check.Readability.PredicateFunctionNames, []}, {Credo.Check.Readability.PreferImplicitTry, []}, {Credo.Check.Readability.RedundantBlankLines, []}, {Credo.Check.Readability.Semicolons, []}, + {Credo.Check.Readability.SeparateAliasRequire, []}, + {Credo.Check.Readability.SinglePipe, []}, {Credo.Check.Readability.SpaceAfterCommas, []}, + {Credo.Check.Readability.Specs, false}, + {Credo.Check.Readability.StrictModuleLayout, + [ + order: + ~w(moduledoc behaviour use import require alias module_attribute defstruct callback macrocallback optional_callback)a, + ignore: [:type], + ignore_module_attributes: [:tag, :trace] + ]}, {Credo.Check.Readability.StringSigils, []}, {Credo.Check.Readability.TrailingBlankLine, []}, {Credo.Check.Readability.TrailingWhiteSpace, []}, {Credo.Check.Readability.UnnecessaryAliasExpansion, []}, {Credo.Check.Readability.VariableNames, []}, + {Credo.Check.Readability.WithCustomTaggedTuple, []}, # ## Refactoring Opportunities # + {Credo.Check.Refactor.ABCSize, false}, + {Credo.Check.Refactor.AppendSingleItem, []}, {Credo.Check.Refactor.CondStatements, []}, {Credo.Check.Refactor.CyclomaticComplexity, []}, + {Credo.Check.Refactor.DoubleBooleanNegation, []}, {Credo.Check.Refactor.FunctionArity, []}, {Credo.Check.Refactor.LongQuoteBlocks, []}, - {Credo.Check.Refactor.MapInto, []}, + # {Credo.Check.Refactor.MapInto, []}, {Credo.Check.Refactor.MatchInCondition, []}, + {Credo.Check.Refactor.ModuleDependencies, false}, {Credo.Check.Refactor.NegatedConditionsInUnless, []}, {Credo.Check.Refactor.NegatedConditionsWithElse, []}, - {Credo.Check.Refactor.Nesting, max_nesting: 3}, + {Credo.Check.Refactor.NegatedIsNil, []}, + {Credo.Check.Refactor.Nesting, []}, + {Credo.Check.Refactor.PipeChainStart, []}, {Credo.Check.Refactor.UnlessWithElse, []}, + {Credo.Check.Refactor.VariableRebinding, false}, {Credo.Check.Refactor.WithClauses, []}, # ## Warnings # + {Credo.Check.Warning.ApplicationConfigInModuleAttribute, []}, {Credo.Check.Warning.BoolOperationOnSameValues, []}, {Credo.Check.Warning.ExpensiveEmptyEnumCheck, []}, {Credo.Check.Warning.IExPry, []}, {Credo.Check.Warning.IoInspect, []}, - {Credo.Check.Warning.LazyLogging, []}, - {Credo.Check.Warning.MixEnv, false}, + {Credo.Check.Warning.LeakyEnvironment, []}, + # {Credo.Check.Warning.LazyLogging, []}, + {Credo.Check.Warning.MapGetUnsafePass, []}, + # disabling this check by default, as if not included, it will be + # run on version 1.7.0 and above + {Credo.Check.Warning.MissedMetadataKeyInLoggerConfig, []}, + {Credo.Check.Warning.MixEnv, []}, {Credo.Check.Warning.OperationOnSameValues, []}, {Credo.Check.Warning.OperationWithConstantResult, []}, {Credo.Check.Warning.RaiseInsideRescue, []}, + {Credo.Check.Warning.UnsafeExec, []}, + {Credo.Check.Warning.UnsafeToAtom, []}, {Credo.Check.Warning.UnusedEnumOperation, []}, {Credo.Check.Warning.UnusedFileOperation, []}, {Credo.Check.Warning.UnusedKeywordOperation, []}, @@ -146,38 +173,7 @@ {Credo.Check.Warning.UnusedPathOperation, []}, {Credo.Check.Warning.UnusedRegexOperation, []}, {Credo.Check.Warning.UnusedStringOperation, []}, - {Credo.Check.Warning.UnusedTupleOperation, []}, - {Credo.Check.Warning.UnsafeExec, []}, - - # - # Checks scheduled for next check update (opt-in for now, just replace `false` with `[]`) - - # - # Controversial and experimental checks (opt-in, just replace `false` with `[]`) - # - {Credo.Check.Readability.StrictModuleLayout, []}, - {Credo.Check.Consistency.MultiAliasImportRequireUse, []}, - {Credo.Check.Consistency.UnusedVariableNames, false}, - {Credo.Check.Design.DuplicatedCode, []}, - {Credo.Check.Readability.AliasAs, false}, - {Credo.Check.Readability.MultiAlias, []}, - {Credo.Check.Readability.Specs, []}, - {Credo.Check.Readability.SinglePipe, []}, - {Credo.Check.Readability.WithCustomTaggedTuple, false}, - {Credo.Check.Refactor.ABCSize, false}, - {Credo.Check.Refactor.AppendSingleItem, []}, - {Credo.Check.Refactor.DoubleBooleanNegation, []}, - {Credo.Check.Refactor.ModuleDependencies, false}, - {Credo.Check.Refactor.NegatedIsNil, []}, - {Credo.Check.Refactor.PipeChainStart, []}, - {Credo.Check.Refactor.VariableRebinding, []}, - {Credo.Check.Warning.MapGetUnsafePass, false}, - {Credo.Check.Warning.UnsafeToAtom, false}, - {Credo.Check.Warning.LeakyEnvironment, []} - - # - # Custom checks can be created using `mix credo.gen.check`. - # + {Credo.Check.Warning.UnusedTupleOperation, []} ] } ] diff --git a/.formatter.exs b/.formatter.exs index beb038c..a291e6a 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -1,6 +1,8 @@ -# Used by "mix format" +# This file is synced with beam-community/common-config. Any changes will be overwritten. + [ - inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"], - import_deps: [:typed_struct, :stream_data], - line_length: 120 + import_deps: [:stream_data, :typed_struct], + inputs: ["*.{heex,ex,exs}", "{config,lib,priv,test}/**/*.{heex,ex,exs}"], + line_length: 120, + plugins: [] ] diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4e4f815..43b776a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,5 +1 @@ -# Order alphabetically. -# Order is important. The last matching pattern takes the most precedence. - -# Default owners for everything in the repo. -* @beam-community/team @beam-community/avro +* @beam-community/team diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ed3cbfb --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,20 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + commit-message: + prefix: "chore(deps)" + + - package-ecosystem: mix + directory: "/" + schedule: + interval: weekly + commit-message: + prefix: "chore(deps)" + groups: + prod: + dependency-type: production + dev: + dependency-type: development diff --git a/.github/release-please-config.json b/.github/release-please-config.json new file mode 100644 index 0000000..f4e6014 --- /dev/null +++ b/.github/release-please-config.json @@ -0,0 +1,39 @@ +{ + "$comment": "This file is synced with beam-community/common-config. Any changes will be overwritten.", + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "changelog-sections": [ + { + "type": "feat", + "section": "Features", + "hidden": false + }, + { + "type": "fix", + "section": "Bug Fixes", + "hidden": false + }, + { + "type": "refactor", + "section": "Miscellaneous", + "hidden": false + } + ], + "draft": false, + "draft-pull-request": false, + "packages": { + ".": { + "extra-files": [ + "README.md" + ], + "release-type": "elixir" + } + }, + "plugins": [ + { + "type": "sentence-case" + } + ], + "prerelease": false, + "pull-request-header": "An automated release has been created for you.", + "separate-pull-requests": true +} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..abfed54 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,121 @@ +# This file is synced with beam-community/common-config. Any changes will be overwritten. + +name: CI + +on: + merge_group: + pull_request: + types: + - opened + - reopened + - synchronize + push: + branches: + - main + workflow_call: + secrets: + GH_PERSONAL_ACCESS_TOKEN: + required: true + workflow_dispatch: + +concurrency: + group: CI ${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + Credo: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Elixir + uses: stordco/actions-elixir/setup@v1 + with: + github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} + + - name: Credo + run: mix credo --strict + + Dependencies: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Elixir + uses: stordco/actions-elixir/setup@v1 + with: + github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} + + - name: Unused + run: mix deps.unlock --check-unused + + Dialyzer: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Elixir + uses: stordco/actions-elixir/setup@v1 + with: + github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} + + - name: Dialyzer + run: mix dialyzer --format github + + Format: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Elixir + uses: stordco/actions-elixir/setup@v1 + with: + github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} + + - name: Format + run: mix format --check-formatted + + Test: + name: Test (Elixir ${{ matrix.versions.elixir }} OTP ${{ matrix.versions.otp }}) + + runs-on: ubuntu-latest + + env: + MIX_ENV: test + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Elixir + uses: stordco/actions-elixir/setup@v1 + with: + elixir-version: ${{ matrix.versions.elixir }} + github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} + otp-version: ${{ matrix.versions.otp }} + + - name: Compile + run: mix compile --warnings-as-errors + + - name: Test + run: mix test + + strategy: + fail-fast: false + matrix: + versions: + - elixir: 1.15 + otp: 26 + - elixir: 1.16 + otp: 26 + - elixir: 1.17 + otp: 27 + diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml new file mode 100644 index 0000000..a176a04 --- /dev/null +++ b/.github/workflows/pr.yaml @@ -0,0 +1,43 @@ +# This file is synced with beam-community/common-config. Any changes will be overwritten. + +name: PR + +on: + merge_group: + pull_request: + types: + - edited + - opened + - reopened + - synchronize + +jobs: + Title: + if: ${{ github.event_name == 'pull_request' }} + name: Check Title + runs-on: ubuntu-latest + + steps: + - name: Check + uses: stordco/actions-pr-title@v1.0.0 + with: + regex: '^(refactor!|feat!|fix!|refactor|fix|feat|chore)(\(\w+\))?:\s(\[#\d{1,5}\])?.*$' + hint: | + Your PR title does not match the Conventional Commits convention. Please rename your PR to match one of the following formats: + + fix: [#123] some title of the PR + fix(scope): [#123] some title of the PR + feat: [#1234] some title of the PR + chore: update some action + + Note: Adding ! (i.e. `feat!:`) represents a breaking change and will result in a SemVer major release. + + Please use one of the following types: + + - **feat:** A new feature, resulting in a MINOR version bump. + - **fix:** A bug fix, resulting in a PATCH version bump. + - **refactor:** A code change that neither fixes a bug nor adds a feature. + - **chore:** Changes unrelated to the release code, resulting in no version bump. + - **revert:** Reverts a previous commit. + + See https://www.conventionalcommits.org/en/v1.0.0/ for more information. diff --git a/.github/workflows/production.yaml b/.github/workflows/production.yaml new file mode 100644 index 0000000..6304a1e --- /dev/null +++ b/.github/workflows/production.yaml @@ -0,0 +1,35 @@ +# This file is synced with beam-community/common-config. Any changes will be overwritten. + +name: Production + +on: + release: + types: + - released + - prereleased + workflow_dispatch: + +concurrency: + group: Production + +jobs: + Hex: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Elixir + uses: stordco/actions-elixir/setup@v1 + with: + github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} + + - name: Compile + run: mix compile --docs + + - name: Publish + run: mix hex.publish --yes + env: + HEX_API_KEY: ${{ secrets.HEX_API_KEY }} + diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..674f5c2 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,23 @@ +# This file is synced with beam-community/common-config. Any changes will be overwritten. + +name: Release + +on: + push: + branches: + - main + +jobs: + Please: + runs-on: ubuntu-latest + + steps: + - id: release + name: Release + uses: google-github-actions/release-please-action@v4 + with: + command: manifest + config-file: .github/release-please-config.json + manifest-file: .github/release-please-manifest.json + release-type: elixir + token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 0000000..0e50960 --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,47 @@ +name: "Close stale issues and PRs" + +on: + workflow_dispatch: + schedule: + - cron: "30 1 * * *" + +permissions: + contents: write + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + days-before-issue-stale: 30 + days-before-issue-close: 15 + days-before-pr-stale: 60 + days-before-pr-close: 60 + + stale-issue-label: "stale:discard" + exempt-issue-labels: "stale:keep" + stale-issue-message: > + This issue has been automatically marked as "stale:discard". We are sorry that we haven't been able to + prioritize it yet. + + If this issue still relevant, please leave any comment if you have any new additional information that + helps to solve this issue. We encourage you to create a pull request, if you can. We are happy to help you + with that. + + close-issue-message: > + Closing this issue after a prolonged period of inactivity. If this issue is still relevant, feel free to + re-open the issue. Thank you! + + stale-pr-label: "stale:discard" + exempt-pr-labels: "stale:keep" + stale-pr-message: > + This pull request has been automatically marked as "stale:discard". **If this pull request is still + relevant, please leave any comment** (for example, "bump"), and we'll keep it open. We are sorry that we + haven't been able to prioritize reviewing it yet. + Your contribution is very much appreciated!. + close-pr-message: > + Closing this pull request after a prolonged period of inactivity. If this issue is still relevant, please + ask for this pull request to be reopened. Thank you! diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..fe29d91 --- /dev/null +++ b/.tool-versions @@ -0,0 +1,2 @@ +elixir 1.16 +erlang 26.0 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..063f6cb --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +# MIT License + +Copyright (c) 2024 BEAM Community + +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.