diff --git a/.github/actions/dart_package/action.yaml b/.github/actions/dart_package/action.yaml new file mode 100644 index 000000000..69fcdffe9 --- /dev/null +++ b/.github/actions/dart_package/action.yaml @@ -0,0 +1,100 @@ +name: Dart Package Workflow +description: Build and test Dart packages. + +inputs: + collect_coverage: + required: false + default: "true" + description: Whether to collect code coverage + collect_score: + required: false + default: "true" + description: Whether to collect the pana score + concurrency: + required: false + default: "4" + description: The value of the concurrency flag (-j) used when running tests + coverage_excludes: + required: false + default: "" + description: Globs to exclude from coverage + dart_sdk: + required: false + default: "stable" + description: "The dart sdk version to use" + working_directory: + required: false + default: "." + description: The working directory for this workflow + min_coverage: + required: false + default: "100" + description: The minimum coverage percentage value + min_score: + required: false + default: "120" + description: The minimum pana score value + analyze_directories: + required: false + default: "lib test" + description: Directories to analyze + report_on: + required: false + default: "lib" + description: Directories to report on when collecting coverage + run_tests: + required: false + default: "true" + description: Whether to run tests for the package. + +runs: + using: "composite" + steps: + - name: ๐ŸŽฏ Setup Dart + uses: dart-lang/setup-dart@v1 + with: + sdk: ${{inputs.dart_sdk}} + + - name: ๐Ÿ“ฆ Install Dependencies + working-directory: ${{ inputs.working_directory }} + shell: ${{ inputs.shell }} + run: dart pub get + + - name: โœจ Format + working-directory: ${{ inputs.working_directory }} + shell: ${{ inputs.shell }} + run: dart format --set-exit-if-changed . + + - name: ๐Ÿ” Analyze + working-directory: ${{ inputs.working_directory }} + shell: ${{ inputs.shell }} + run: dart analyze --fatal-warnings ${{inputs.analyze_directories}} + + - name: ๐Ÿงช Test + if: inputs.run_tests == 'true' + working-directory: ${{ inputs.working_directory }} + shell: ${{ inputs.shell }} + run: | + dart pub global activate coverage + dart test -j ${{inputs.concurrency}} --coverage=coverage && dart pub global run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=${{inputs.report_on}} --check-ignore + + - name: ๐Ÿ“Š Verify Coverage + if: inputs.run_tests == 'true' && inputs.collect_coverage == 'true' + uses: VeryGoodOpenSource/very_good_coverage@v3 + with: + path: ${{inputs.working_directory}}/coverage/lcov.info + exclude: ${{inputs.coverage_excludes}} + min_coverage: ${{inputs.min_coverage}} + + - name: ๐Ÿ’ฏ Verify Pub Score + if: inputs.collect_score == 'true' + working-directory: ${{ inputs.working_directory }} + shell: ${{ inputs.shell }} + run: | + dart pub global activate pana 0.22.21 + sudo apt-get install webp + PANA=$(pana . --no-warning); PANA_SCORE=$(echo $PANA | sed -n "s/.*Points: \([0-9]*\)\/\([0-9]*\)./\1\/\2/p") + echo "score: $PANA_SCORE" + IFS='/'; read -a SCORE_ARR <<< "$PANA_SCORE"; SCORE=SCORE_ARR[0]; TOTAL=SCORE_ARR[1] + if [ -z "$1" ]; then MINIMUM_SCORE=TOTAL; else MINIMUM_SCORE=$1; fi + if (( $SCORE < $MINIMUM_SCORE )); then echo "minimum score $MINIMUM_SCORE was not met!"; exit 1; fi diff --git a/.github/workflows/dart_frog_lint.yaml b/.github/workflows/dart_frog_lint.yaml new file mode 100644 index 000000000..bfcb03941 --- /dev/null +++ b/.github/workflows/dart_frog_lint.yaml @@ -0,0 +1,30 @@ +name: dart_frog_lint + +on: + pull_request: + paths: + - ".github/workflows/dart_frog_lint.yaml" + - "packages/dart_frog_lint/lib/**" + - "packages/dart_frog_lint/pubspec.yaml" + push: + branches: + - main + paths: + - ".github/workflows/dart_frog_lint.yaml" + - "packages/dart_frog_lint/lib/**" + - "packages/dart_frog_lint/pubspec.yaml" + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: ๐Ÿ“š Git Checkout + uses: actions/checkout@v4 + + - name: ๐ŸŽฏ Build + uses: ./.github/actions/dart_package + with: + analyze_directories: lib + run_tests: false # there aren't any tests since this is just a single yaml file. + working_directory: packages/dart_frog_lint diff --git a/.github/workflows/publish_dart_frog_lint.yaml b/.github/workflows/publish_dart_frog_lint.yaml new file mode 100644 index 000000000..913143671 --- /dev/null +++ b/.github/workflows/publish_dart_frog_lint.yaml @@ -0,0 +1,22 @@ +name: publish/dart_frog_lint + +on: + push: + tags: + - "dart_frog_lint-v[0-9]+.[0-9]+.[0-9]+*" + +jobs: + publish: + environment: pub.dev + runs-on: ubuntu-latest + permissions: + id-token: write # Required for authentication using OIDC + + steps: + - name: ๐Ÿ“š Git Checkout + uses: actions/checkout@v4 + + - name: ๐Ÿ“ฆ Publish + uses: ./.github/actions/pub_publish + with: + working_directory: packages/dart_frog_lint diff --git a/packages/dart_frog_lint/.gitignore b/packages/dart_frog_lint/.gitignore new file mode 100644 index 000000000..cc063e820 --- /dev/null +++ b/packages/dart_frog_lint/.gitignore @@ -0,0 +1,10 @@ +# See https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +build/ +pubspec.lock + +# Test related files +coverage/ \ No newline at end of file diff --git a/packages/dart_frog_lint/CHANGELOG.md b/packages/dart_frog_lint/CHANGELOG.md new file mode 100644 index 000000000..2d5599a50 --- /dev/null +++ b/packages/dart_frog_lint/CHANGELOG.md @@ -0,0 +1,3 @@ +# 0.1.0 + +- feat: initial release ๐ŸŽ‰ diff --git a/packages/dart_frog_lint/LICENSE b/packages/dart_frog_lint/LICENSE new file mode 100644 index 000000000..32bc63089 --- /dev/null +++ b/packages/dart_frog_lint/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Dart Frog Dev + +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 diff --git a/packages/dart_frog_lint/README.md b/packages/dart_frog_lint/README.md new file mode 100644 index 000000000..d6eba6319 --- /dev/null +++ b/packages/dart_frog_lint/README.md @@ -0,0 +1,49 @@ +[](https://dart-frog.dev/) + +### Dart Frog Lint + +
+ +[![discord][discord_badge]][discord_link] +[![dart][dart_badge]][dart_link] + +[![ci][ci_badge]][ci_link] +[![coverage][coverage_badge]][ci_link] +[![pub package][pub_badge]][pub_link] +[![style: very good analysis][very_good_analysis_badge]][very_good_analysis_link] +[![License: MIT][license_badge]][license_link] + +A collection of lint rules built specifically for [Dart Frog][docs_link]. + +## Documentation ๐Ÿ“ + +For official documentation, please visit [dart-frog.dev][docs_link]. + +## Quick Start ๐Ÿš€ + +1. Install `dart_frog_lint` + + `dart pub add --dev dart_frog_lint` + +1. Add an `analysis_options.yaml` to the root of your project with the recommended rules + + ```yaml + include: package:dart_frog_lint/recommended.yaml + ``` + +[ci_badge]: https://github.com/dart-frog-dev/dart_frog/actions/workflows/dart_frog_lint.yaml/badge.svg?branch=main +[ci_link]: https://github.com/dart-frog-dev/dart_frog/actions/workflows/dart_frog_lint.yaml +[coverage_badge]: https://raw.githubusercontent.com/dart-frog-dev/dart_frog/main/packages/dart_frog_lint/coverage_badge.svg +[dart_badge]: https://img.shields.io/badge/Dart-%230175C2.svg?style=for-the-badge&logo=dart&logoColor=5BB4F0&color=1E2833 +[dart_link]: https://dart.dev +[discord_badge]: https://img.shields.io/discord/1394707782271238184?style=for-the-badge&logo=discord&color=1C2A2E&logoColor=1DF9D2 +[discord_link]: https://discord.gg/dart-frog +[docs_link]: https://dart-frog.dev +[license_badge]: https://img.shields.io/badge/license-MIT-blue.svg +[license_link]: https://opensource.org/licenses/MIT +[logo_black]: https://raw.githubusercontent.com/dart-frog-dev/dart_frog/main/assets/dart_frog_logo_black.png#gh-light-mode-only +[logo_white]: https://raw.githubusercontent.com/dart-frog-dev/dart_frog/main/assets/dart_frog_logo_white.png#gh-dark-mode-only +[pub_badge]: https://img.shields.io/pub/v/dart_frog.svg +[pub_link]: https://pub.dartlang.org/packages/dart_frog +[very_good_analysis_badge]: https://img.shields.io/badge/style-very_good_analysis-B22C89.svg +[very_good_analysis_link]: https://pub.dev/packages/very_good_analysis diff --git a/packages/dart_frog_lint/analysis_options.yaml b/packages/dart_frog_lint/analysis_options.yaml new file mode 100644 index 000000000..45d2e04e3 --- /dev/null +++ b/packages/dart_frog_lint/analysis_options.yaml @@ -0,0 +1 @@ +include: ./lib/recommended.yaml diff --git a/packages/dart_frog_lint/assets/logo.png b/packages/dart_frog_lint/assets/logo.png new file mode 100644 index 000000000..a64380703 Binary files /dev/null and b/packages/dart_frog_lint/assets/logo.png differ diff --git a/packages/dart_frog_lint/coverage_badge.svg b/packages/dart_frog_lint/coverage_badge.svg new file mode 100644 index 000000000..499e98ce2 --- /dev/null +++ b/packages/dart_frog_lint/coverage_badge.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + coverage + coverage + 100% + 100% + + diff --git a/packages/dart_frog_lint/example/README.md b/packages/dart_frog_lint/example/README.md new file mode 100644 index 000000000..12bb7e135 --- /dev/null +++ b/packages/dart_frog_lint/example/README.md @@ -0,0 +1,11 @@ +# Dart Frog Lint + +1. Install `dart_frog_lint` + + `dart pub add --dev dart_frog_lint` + +1. Add an `analysis_options.yaml` to the root of your project with the recommended rules + + ```yaml + include: package:dart_frog_lint/recommended.yaml + ``` diff --git a/packages/dart_frog_lint/lib/dart_frog_lint.dart b/packages/dart_frog_lint/lib/dart_frog_lint.dart new file mode 100644 index 000000000..df4696c26 --- /dev/null +++ b/packages/dart_frog_lint/lib/dart_frog_lint.dart @@ -0,0 +1,3 @@ +/// A collection of lint rules built specifically for Dart Frog. +/// Learn more at https://dart-frog.dev +library; diff --git a/packages/dart_frog_lint/lib/recommended.yaml b/packages/dart_frog_lint/lib/recommended.yaml new file mode 100644 index 000000000..6afbc1a7f --- /dev/null +++ b/packages/dart_frog_lint/lib/recommended.yaml @@ -0,0 +1,10 @@ +include: package:very_good_analysis/analysis_options.yaml +analyzer: + exclude: + - build/** +linter: + rules: + # Route names are derived from the respective file names + file_names: false + # Experimental and there are lots of false positives + specify_nonobvious_property_types: false diff --git a/packages/dart_frog_lint/pubspec.yaml b/packages/dart_frog_lint/pubspec.yaml new file mode 100644 index 000000000..4023dc0eb --- /dev/null +++ b/packages/dart_frog_lint/pubspec.yaml @@ -0,0 +1,18 @@ +name: dart_frog_lint +description: A collection of lint rules built specifically for the Dart Frog backend framework. +version: 0.1.0 +homepage: https://dart-frog.dev +repository: https://github.com/dart-frog-dev/dart_frog +issue_tracker: https://github.com/dart-frog-dev/dart_frog/issues +documentation: https://dart-frog.dev/getting-started +topics: [lint, server, backend, shelf, dart-frog] + +screenshots: + - description: Dart Frog logo. + path: assets/logo.png + +environment: + sdk: ">=3.0.0 <4.0.0" + +dependencies: + very_good_analysis: ^9.0.0