diff --git a/.github/cspell.json b/.github/cspell.json index bd2fd776b..b04facb7c 100644 --- a/.github/cspell.json +++ b/.github/cspell.json @@ -31,6 +31,7 @@ "gradlew", "fluttium", "clsx", + "Dartdoc", "mockingjay" ] } diff --git a/.github/workflows/claude.yaml b/.github/workflows/claude.yaml new file mode 100644 index 000000000..3b0b3cb47 --- /dev/null +++ b/.github/workflows/claude.yaml @@ -0,0 +1,43 @@ +name: claude_code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + issues: + types: [opened, assigned] + pull_request_review: + types: [submitted] + +jobs: + claude: + if: | + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + runs-on: ubuntu-latest + permissions: + issues: read + actions: read # Required for Claude to read CI results on PRs + contents: read + id-token: write + pull-requests: read + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + claude_args: | + --max-turns 5 + --model claude-opus-4-6 + # This is an optional setting that allows Claude to read CI results on PRs + additional_permissions: | + actions: read diff --git a/.github/workflows/claude_code_review.yaml b/.github/workflows/claude_code_review.yaml new file mode 100644 index 000000000..26b267c1f --- /dev/null +++ b/.github/workflows/claude_code_review.yaml @@ -0,0 +1,32 @@ +name: claude_code_review + +on: + pull_request: + types: [opened, synchronize, ready_for_review, reopened] + +jobs: + claude-review: + runs-on: ubuntu-latest + permissions: + issues: read + contents: read + id-token: write + pull-requests: read + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code Review + id: claude-review + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + plugin_marketplaces: "https://github.com/anthropics/claude-code.git" + plugins: "code-review@claude-code-plugins" + prompt: "/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}" + claude_args: | + --max-turns 5 + --model claude-opus-4-6 diff --git a/AGENTS.md b/AGENTS.md index 521703af4..f27c140ba 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,11 +11,82 @@ Our criteria for good code also enables us to achieve 100% test coverage. Good code has... -- as few branches as possible -- injectable dependencies -- well-named identifiers -- no sibling dependencies in the same architectural layer +- As few branches as possible +- Injectable dependencies +- Well-named identifiers +- No sibling dependencies in the same architectural layer To avoid sibling dependencies, state must either be lifted up to a common ancestor and passed down, or pushed down and subscribed to. -See CONTRIBUTING.md for development details. +See @CONTRIBUTING.md for development details. + +## Project Overview + +Very Good CLI is a Dart command-line tool by Very Good Ventures for generating scalable project templates and running developer commands. It is published on pub.dev as `very_good_cli`. + +## Common Commands + +```bash +# Install dependencies +dart pub get && cd bricks/test_optimizer && dart pub get && cd ../../ + +# Run unit tests (excludes expensive pull-request-only and e2e tests) +flutter test -x pull-request-only -x e2e + +# Run a single test file +flutter test test/src/commands/create/create_test.dart + +# Format code +dart format lib test + +# Analyze code (strict: warnings and infos are fatal) +dart analyze --fatal-infos --fatal-warnings . + +# Auto-fix lint issues +dart fix --apply + +# Activate local dev version +dart pub global activate --source path . +``` + +## Architecture + +### Command Runner Pattern + +Entry point: `bin/very_good.dart` → `VeryGoodCommandRunner` (extends `CompletionCommandRunner`). + +All commands return `Future` (exit codes from `universal_io`'s `ExitCode`). Top-level commands: `create`, `test`, `packages`, `dart`, `update`, `mcp`. + +### Create Command System + +`CreateCommand` has subcommands for each template type (flutter_app, dart_package, dart_cli, docs_site, flame_game, flutter_package, flutter_plugin). + +All subcommands extend `CreateSubCommand` and use mixins for optional features: +- `OrgName` — adds `--org-name` flag +- `MultiTemplates` — supports `--template` flag with multiple template choices +- `Publishable` — adds `--publishable` flag + +Templates use Mason for code generation. Each template has a bundle, a `Template` class, and an `onGenerateComplete` hook. Template source code lives in separate repos under `VeryGoodOpenSource/very_good_templates`. + +### CLI Abstraction Layer (`lib/src/cli/`) + +- `DartCli`, `FlutterCli`, `GitCli` — wrappers around shell commands +- `ProcessOverrides` — zone-based dependency injection for mocking `Process.run` in tests +- `TestCliRunner` — test execution logic with coverage collection + +### Testing Patterns + +- **100% test coverage required** for all PRs +- Mocking with `mocktail` +- Constructor injection for dependencies (`Logger`, `PubUpdater`, generators) +- `@visibleForTesting` used for test-only overrides (e.g., `argResultOverrides`) +- Test tags in `dart_test.yaml`: `pull-request-only` for expensive CI-only tests +- E2E tests in `e2e/` create real projects and run full workflows +- Test optimizer brick in `bricks/test_optimizer/` generates optimized test entry points + +## Code Conventions + +- Linting: `very_good_analysis` (strict Dart analysis rules) +- Dartdoc templates: `/// {@template name}...{@endtemplate}` / `/// {@macro name}` +- Commits follow [Conventional Commits](https://www.conventionalcommits.org/) (used by release-please for automated versioning) +- `lib/src/version.dart` is auto-generated — do not edit manually diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..eef4bd20c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md \ No newline at end of file