diff --git a/.github/workflows/release_please.yaml b/.github/workflows/release_please.yaml new file mode 100644 index 0000000..81b9087 --- /dev/null +++ b/.github/workflows/release_please.yaml @@ -0,0 +1,22 @@ +name: release_please + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + workflow_dispatch: + push: + branches: + - main + +jobs: + create_release_pr: + runs-on: ubuntu-latest + + steps: + - uses: googleapis/release-please-action@v4 + with: + token: ${{ secrets.RELEASE_PLEASE_TOKEN }} + manifest-file: ".release-please-manifest.json" + config-file: ".release-please-config.json" \ No newline at end of file diff --git a/.github/workflows/verify_version.yaml b/.github/workflows/verify_version.yaml new file mode 100644 index 0000000..06f9cb2 --- /dev/null +++ b/.github/workflows/verify_version.yaml @@ -0,0 +1,18 @@ +name: verify_version + +on: + workflow_dispatch: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + verify-version: + if: github.head_ref == 'release-please--branches--main--components--very_good_analysis' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - uses: dart-lang/setup-dart@v1 + + - name: Verify version consistency + run: dart run tool/verify_version/main.dart diff --git a/.release-please-config.json b/.release-please-config.json new file mode 100644 index 0000000..21b17c5 --- /dev/null +++ b/.release-please-config.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "changelog-sections": [ + { "type": "feat", "section": "Features" }, + { "type": "fix", "section": "Bug Fixes" }, + { "type": "refactor","section": "Refactors" }, + { "type": "chore", "section": "Miscellaneous Chores" }, + { "type": "docs", "section": "Docs" } + ], + "pull-request-header": ":rotating_light: There are changes ready for release :rocket:\n\nβ„Ή Merge this PR once the team confirms the release is ready.\n", + "pull-request-title-pattern": "chore: ${version}", + "include-component-in-tag": false, + "packages": { + ".": { + "release-type": "dart", + "changelog-path": "CHANGELOG.md", + "version-file": "pubspec.yaml" + } + }, + "exclude-paths": [ + ".github", + ".release-please-manifest.json", + ".release-please-config.json", + "CONTRIBUTING.md", + "tool" + ] +} \ No newline at end of file diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..8ed0e81 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,4 @@ +{ + ".": "9.0.0" +} + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 271cfbd..6fa8ae4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,18 +1,19 @@ -# 9.0.0 + +## 9.0.0 - chore(deps): bump peter-evans/create-pull-request from 7.0.6 to 7.0.8 [139](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/139) - chore: release 9.0.0-rc.1 [154](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/154) -# 9.0.0-rc.1 +## 9.0.0-rc.1 - feat: support Dart 3.8.0 [152](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/152) -# 8.0.0 +## 8.0.0 - chore: release 8.0.0-rc.1 - fix: remove `omit_obvious_property_types` as it conflicts with `type_annotate_public_apis` [148](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/148) -# 8.0.0-rc.1 +## 8.0.0-rc.1 - feat: add `omit_obvious_property_types` [143](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/143) - feat: add `specify_nonobvious_property_types` [143](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/143) @@ -20,11 +21,11 @@ - feat: add `unnecessary_underscores` [143](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/143) - feat: remove `require_trailing_commas` [143](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/143) -# 7.0.0 +## 7.0.0 - chore: release 7.0.0-dev.1 -# 7.0.0-dev.1 +## 7.0.0-dev.1 - feat: add `document_ignores` [125](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/125) - feat: remove `avoid_null_checks_in_equality_operators` [124](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/124) @@ -36,11 +37,11 @@ - docs: update exclusion reasons [109](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/109) - docs: update commands in contributing [110](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/110) -# 6.0.0 +## 6.0.0 - chore: release 6.0.0-dev.1 -# 6.0.0-dev.1 +## 6.0.0-dev.1 - feat!: upgrade to support Dart `^3.4.0` - feat: additional lint rules: @@ -49,18 +50,18 @@ - [no_wildcard_variable_uses](https://dart.dev/tools/linter-rules/no_wildcard_variable_uses) - docs: include exclusion reason table ([100](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/100), [102](https://github.com/VeryGoodOpenSource/very_good_analysis/pull/102)) -# 5.1.0 +## 5.1.0 - fix: remove deprecated `iterable_contains_unrelated_type` lint - fix: remove deprecated `list_remove_unrelated_type` lint - fix(docs): full list of rules - feat: type equality checks should be warnings/errors -# 5.0.0+1 +## 5.0.0+1 - docs: minor updates to documentation in `README.md` -# 5.0.0 +## 5.0.0 - feat!: upgrade to support Dart `^3.0.0` - feat: added analysis warning as error: @@ -75,11 +76,11 @@ - refactor: remove malfunctioning rules: - [`use_decorated_box`](https://github.com/VeryGoodOpenSource/very_good_analysis/issues/65) -# 4.0.0+1 +## 4.0.0+1 - docs: minor updates to documentation in `README.md` -# 4.0.0 +## 4.0.0 - feat!: upgrade to support Dart `^2.19.0` - feat: additional lint rules: @@ -99,7 +100,7 @@ - [avoid_returning_null](https://dart-lang.github.io/linter/lints/avoid_returning_null.html) - [avoid_returning_null_for_future](https://dart-lang.github.io/linter/lints/avoid_returning_null_for_future.html) -# 3.1.0 +## 3.1.0 - **BREAKING** refactor: remove deprecated `unawaited` (use `unawaited` from `dart:async` instead). - feat: additional lint rules: @@ -112,12 +113,12 @@ - [use_if_null_to_convert_nulls_to_bools](https://dart-lang.github.io/linter/lints/use_if_null_to_convert_nulls_to_bools.html) - [use_test_throws_matchers](https://dart-lang.github.io/linter/lints/use_test_throws_matchers.html) -# 3.0.2 +## 3.0.2 - fix: remove deprecated `invariant_booleans` lint - fix: deprecate `unawaited` (use `unawaited` from `dart:async` instead). -# 3.0.1 +## 3.0.1 - feat: use analyzer language modes instead of deprecated `strong-mode` ```yaml @@ -127,7 +128,7 @@ strict-raw-types: true ``` -# 3.0.0 +## 3.0.0 - feat!: upgrade to support Dart `^2.17.0` - feat: additional lint rules: @@ -141,7 +142,7 @@ - [use_enums](https://dart-lang.github.io/linter/lints/use_enums.html) - [use_super_parameters](https://dart-lang.github.io/linter/lints/use_super_parameters.html) -# 2.4.0 +## 2.4.0 - feat: additional lint rules: - [`avoid_js_rounded_ints`](https://dart-lang.github.io/linter/lints/avoid_js_rounded_ints.html) @@ -160,7 +161,7 @@ - [`require_trailing_commas`](https://dart-lang.github.io/linter/lints/require_trailing_commas.html) - [`use_is_even_rather_than_modulo`](https://dart-lang.github.io/linter/lints/use_is_even_rather_than_modulo.html) -# 2.3.0 +## 2.3.0 - feat: additional analysis errors: - `missing_required_param` @@ -206,7 +207,7 @@ - [`unnecessary_parenthesis`](https://dart-lang.github.io/linter/lints/unnecessary_parenthesis.html) - [`unnecessary_raw_strings`](https://dart-lang.github.io/linter/lints/unnecessary_raw_strings.html) -# 2.2.0 +## 2.2.0 - feat: additional lint rules: - `always_use_package_imports` @@ -214,19 +215,19 @@ - `avoid_slow_async_io` - `avoid_type_to_string` -# 2.1.2 +## 2.1.2 - refactor: remove deprecated `pedantic` dependency - ci: improvements to ensure max pub score - docs: minor documentation and package description updates -# 2.1.1 +## 2.1.1 - docs: update `README` to include latest version - docs: reword package description - docs: consolidate `README` links -# 2.1.0 +## 2.1.0 - feat: update sdk constraint to v2.12.0 stable - feat: additional lint rules: @@ -255,34 +256,34 @@ - `use_full_hex_values_for_flutter_colors` - `void_checks` -# 2.0.3 +## 2.0.3 - feat: additional linter rule: - `sort_child_properties_last` -# 2.0.2 +## 2.0.2 - feat: additional linter rule: - `use_key_in_widget_constructors` -# 2.0.1 +## 2.0.1 - feat: additional linter rule: - `avoid_dynamic_calls` -# 2.0.0 +## 2.0.0 - feat: stable null safe release -# 2.0.0-nullsafety.0 +## 2.0.0-nullsafety.0 - chore: migrate to null safety -# 1.0.4 +## 1.0.4 - docs: README and metadata updates -# 1.0.3 +## 1.0.3 - feat: additional linter rules - `avoid_print` @@ -292,15 +293,15 @@ - `prefer_const_declarations` - `sized_box_for_whitespace` -# 1.0.2 +## 1.0.2 - feat: add test/.test_coverage.dart to the list of ignored files -# 1.0.1 +## 1.0.1 - docs: README improvements - docs: inline documentation improvements -# 1.0.0 +## 1.0.0 - Add `analysis_options` used at [Very Good Ventures](https://verygood.ventures) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 895eb77..82fb625 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,17 +17,31 @@ but we still recommend to file an issue detailing what you’re fixing. This is helpful in case we don’t accept that specific fix but want to keep track of the issue. -## Contributing new Dart lint rules +## Add or remove rules -If you intend to provide changes related to a new Dart version you can follow these steps: +If you intend to provide changes related to a add or remove rules you can follow these steps: + +1. Run `dart tool/bump_version/main.dart ` to generate a new version. + - Choose `` according to [Semantic Versioning](https://semver.org/) guidelines based on your proposed changes. +1. Add or remove the lint rules you want to change in the version file you generated in step 1. +1. Document the rules that were removed with a reason as to why, if there is any. + - Link to an issue as to why a lint rule should not be used if there is any. +1. Create a pull request following the guidelines in the [Creating a Pull Request](#creating-a-pull-request) section below. + + +## Contributing rules from a new Dart version + +If you intend to provide changes related to a **new Dart version** you can follow these steps: 1. Ensure you are on the latest stable Dart version. 1. Run `dart tool/bump_version/main.dart ` to generate a new version. + - Choose `` according to [Semantic Versioning](https://semver.org/) guidelines based on your proposed changes. 1. Add or remove the lint rules you want to change in the version file you generated in step 2. - > To find new rules more easily you can run the same command as in step 4 which will add new rules directly to the exclusion table. + - To find new rules more easily you can run the same command as in step 4 which will add new rules directly to the exclusion table. 1. Open a terminal in `tool/linter_rules` and run `dart lib/exclusion_reason_table.dart` to generate an up-to-date exclusion table. 1. Document the rules that were removed with a reason as to why, if there is any. - > Link to an issue as to why a lint rule should not be used if there is any. + - Link to an issue as to why a lint rule should not be used if there is any. +1. Create a pull request following the guidelines in the [Creating a Pull Request](#creating-a-pull-request) section below. ## Creating a Pull Request @@ -42,34 +56,68 @@ Before creating a pull request please: 1. If you've changed the public API, make sure to update/add documentation. 1. Format your code (`dart format .`). 1. Analyze your code (`dart analyze . --fatal-infos`). +1. Follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0) specification for your commit messages. + - This enables automatic version bumping and changelog generation as detailed in the [Release Process](#release-process) section. 1. Create the Pull Request. 1. Verify that all status checks are passing. + While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted. -## Releasing new versions -Every snapshot of a version is saved on its own yaml file under the name pattern: `lib/analysis_options..yaml`. +## Release Process πŸš€ + + ##### ‼️ Important + - Every snapshot of a version is saved on its own yaml file under the name pattern: `lib/analysis_options..yaml`. + + +We use [`release-please-action`][release-please-action-link] to automate versioning and changelog generation, along with a GitHub workflow that automatically publish the Very Good Analysis to pub.dev. + +### How it works: + +- πŸ“Œ **On Every Commit to main:** + - Commits are analyzed using [Conventional Commits][conventional_commits_link]. + - If a version bump is needed, a **release PR** is automatically created or updated by [`release-please-action`][release-please-action-link]. + - The **release PR** includes: + - An updated `CHANGELOG.md` + - A version bump in `pubspec.yaml` + + ##### ‼️ Important + - A version verification workflow (`.github/workflows/verify_version.yaml`) runs to ensure: + - The version in `pubspec.yaml` matches the version in `lib/analysis_options.yaml` + - The file `lib/analysis_options_.yaml` exists + - If any mismatches are found, the files need to be manually updated to match + + ##### πŸ’‘ Notes -### Release a new version + - The GitHub Action workflow that automates the release process is configured in `.github/workflows/release_please.yaml` + - release-please settings are defined in `.release-please-config.json` and `.release-please-manifest.json` + - The release PR can be manually edited before merging. + - The release PR should be merged **ONLY** when a new release is needed. -Skip step `1` if a new version file was already generated. +
-1. Run the `bump_version` script with the desired new version as an argument: +- βœ… **When the Release PR Is Merged:** + - A new Git tag is created. + - A GitHub Release is published with the changelog. + - A new version of Very Good Analysis is automatically published in pub.dev. - ```sh - dart tool/bump_version/main.dart - ``` + #### πŸ’‘ Notes - Where `` is the new version to be released in the format `x.y.z`. + - The publishing process is automatically triggered when a version tag is created. + - The automated publishing workflow to pub.dev is defined in `.github/workflows/pub_publish.yaml` - This script will: +
- - Copy the most recent yaml to a new one with the new desired version. - - Include that file on the main yaml file `lib/analysis_options.yaml`. +This document provides a good summary of how it works and how we use it, but we recommend that you also read the official documentation of [Conventional Commits][conventional_commits_link], [Semantic Versioning][sem_ver_link], [Publishing Dart packages][dart_publishing_link] and [`release-please-action`][release-please-action-link]. -1. Update the `README.md` exclusion table, refer to the ["Exclusion Reason Table πŸ—žοΈπŸ‘¨β€βš–οΈ"](tool/linter_rules/README.md#exclusion-reason-table-️️) documentation for more information. -1. Open a pull request with the proposed changes. +[dart_publishing_link]: https://dart.dev/tools/pub/publishing +[sem_ver_link]: https://semver.org/ +[release-please-action-link]: https://github.com/googleapis/release-please-action +[conventional_commits_link]: https://www.conventionalcommits.org/en/v1.0.0 +[bug_report_link]: https://github.com/VeryGoodOpenSource/very_good_cli/issues/new?assignees=&labels=bug&template=bug_report.md&title=fix%3A+ +[very_good_core_link]: doc/very_good_core.md +[very_good_ventures_link]: https://verygood.ventures/?utm_source=github&utm_medium=banner&utm_campaign=CLI diff --git a/tool/verify_version/main.dart b/tool/verify_version/main.dart new file mode 100644 index 0000000..6cacfe3 --- /dev/null +++ b/tool/verify_version/main.dart @@ -0,0 +1,58 @@ +import 'dart:io'; + +/// Verifies that the version in pubspec.yaml matches the version in +/// lib/analysis_options.yaml and lib/analysis_options.${version}.yaml. +void main() { + final pubspecFile = File('pubspec.yaml'); + final analysisOptionsFile = File('lib/analysis_options.yaml'); + + if (!pubspecFile.existsSync()) { + stderr.writeln('❌ pubspec.yaml not found.'); + exit(1); + } + if (!analysisOptionsFile.existsSync()) { + stderr.writeln('❌ lib/analysis_options.yaml not found.'); + exit(1); + } + + // Extract version from pubspec.yaml + final pubspecContent = pubspecFile.readAsStringSync(); + final pubspecVersionMatch = + RegExp(r'version:\s*([\d]+\.[\d]+\.[\d]+)').firstMatch(pubspecContent); + + if (pubspecVersionMatch == null) { + stderr.writeln('❌ Could not find a valid version in pubspec.yaml.'); + exit(1); + } + final pubspecVersion = pubspecVersionMatch.group(1)!; + + final versionedAnalysisFile = + File('lib/analysis_options.$pubspecVersion.yaml'); + if (!versionedAnalysisFile.existsSync()) { + stderr.writeln('❌ lib/analysis_options.$pubspecVersion.yaml not found.'); + exit(1); + } + + // Extract version from lib/analysis_options.yaml + final analysisContent = analysisOptionsFile.readAsStringSync(); + final includeMatch = RegExp( + r'include:\s*package:very_good_analysis/analysis_options\.(\d+\.\d+\.\d+)\.yaml', + ).firstMatch(analysisContent); + + if (includeMatch == null) { + stderr.writeln('❌ Could not find version in lib/analysis_options.yaml.'); + exit(1); + } + final analysisVersion = includeMatch.group(1)!; + + // Compare versions + if (pubspecVersion != analysisVersion) { + stderr.writeln('❌ Version mismatch:\n' + '- pubspec.yaml version: $pubspecVersion\n' + '- lib/analysis_options.yaml version: $analysisVersion\n\n' + 'Please update lib/analysis_options.yaml to match pubspec.yaml.'); + exit(1); + } + + print('βœ… Versions match: $pubspecVersion'); +}