|
1 | | -Read CLAUDE.md for instructions |
| 1 | +# LogStruct Development Guide |
| 2 | + |
| 3 | +## 🚨 CRITICAL RULES - MUST ALWAYS BE FOLLOWED 🚨 |
| 4 | + |
| 5 | +1. **NEVER mark a feature as done until `./scripts/all_check.sh` is passing** |
| 6 | +2. **ALWAYS run `./scripts/all_check.sh` before claiming completion** |
| 7 | +3. **NO EXCEPTIONS to the above rules - features are NOT complete until all checks pass** |
| 8 | +4. **This rule must ALWAYS be followed no matter what** |
| 9 | + |
| 10 | +## Commands |
| 11 | + |
| 12 | +### Core Commands |
| 13 | + |
| 14 | +- Setup: `scripts/setup.sh` |
| 15 | +- Run all checks: `scripts/all_check.sh` (runs typecheck, export, lint, test, etc.) |
| 16 | +- Run all checks with auto-fix: `scripts/all_write.sh` |
| 17 | +- Interactive console: `scripts/console.rb` |
| 18 | + |
| 19 | +### Testing Commands |
| 20 | + |
| 21 | +- Run all tests (unit + Rails integration): `scripts/all_tests.sh` |
| 22 | +- Run all Ruby unit tests: `scripts/test.rb` |
| 23 | +- Run single test file: `scripts/test.rb test/path_to_test.rb` |
| 24 | +- Run test at specific line: `scripts/test.rb test/path_to_test.rb:LINE_NUMBER` |
| 25 | +- Run test by name: `scripts/test.rb -n=test_method_name` |
| 26 | +- Debug a specific test: Add `debugger` statements (developer only) |
| 27 | +- Run Rails integration tests: `scripts/rails_tests.sh` |
| 28 | +- Merge coverage reports: `scripts/merge_coverage.sh` |
| 29 | +- Run Next.js TypeScript tests: `cd site && npm test` |
| 30 | + |
| 31 | +### Quality Commands |
| 32 | + |
| 33 | +- Ruby typecheck: `scripts/typecheck.sh` |
| 34 | +- Next.js typecheck: `cd site && pnpm exec tsc --noEmit` |
| 35 | +- Lint Ruby: `scripts/rubocop.rb` |
| 36 | +- Format Ruby: `scripts/rubocop.rb -A` |
| 37 | +- Format JS/TS/JSON: `scripts/prettier.sh --write` |
| 38 | +- Lint JS/TS/JSON: `scripts/prettier.sh --check` |
| 39 | +- Spellcheck: `scripts/spellcheck.sh` |
| 40 | + |
| 41 | +### Development Commands |
| 42 | + |
| 43 | +- Generate Sorbet RBI files: `scripts/tapioca.rb` |
| 44 | +- Generate spellcheck dictionary: `scripts/generate_lockfile_words.sh` |
| 45 | +- Generate TypeScript types from Ruby log structs: `scripts/export_typescript_types.rb` |
| 46 | + |
| 47 | +## Terraform Provider repo in this workspace |
| 48 | + |
| 49 | +- The Terraform provider lives in a separate GitHub repo: `DocSpring/terraform-provider-logstruct`. |
| 50 | +- For convenience, the provider repo is checked out as a plain directory at `./terraform-provider-logstruct/` in this repo. It is NOT a Git submodule and is ignored by this repo’s `.gitignore`. |
| 51 | +- You can inspect/build it locally: |
| 52 | + - `cd terraform-provider-logstruct` |
| 53 | + - `go build ./...` |
| 54 | + - Changes you make here are not committed by this repo. To contribute to the provider, commit from inside its directory and push to its own remote. |
| 55 | + |
| 56 | +## Automated releases (gem + provider) |
| 57 | + |
| 58 | +- Workflow: `.github/workflows/release.yml` ("Release Gem + Sync Terraform Provider"). |
| 59 | +- Triggers: |
| 60 | + - Push tag matching `v*` (e.g., `v0.0.1-rc1`, `v0.2.0`). |
| 61 | + - GitHub Release published. |
| 62 | + - Manual run (workflow_dispatch) with `dry_run` input. |
| 63 | +- Behavior: |
| 64 | + - Builds and publishes the Ruby gem to RubyGems (requires `RUBYGEMS_API_KEY`). |
| 65 | + - Regenerates the provider’s embedded catalog (`scripts/export_provider_catalog.rb`), builds the provider, commits catalog changes, and tags the provider repo with the same version. |
| 66 | + - Enforces version alignment: the tag `vX.Y.Z` (or RC) must match `lib/log_struct/version.rb` unless run in dry-run. |
| 67 | + |
| 68 | +## Dry-run mode |
| 69 | + |
| 70 | +- CI dry-run lets you smoke-test the workflow without publishing anything: |
| 71 | + - Actions → "Release Gem + Sync Terraform Provider" → Run workflow → `dry_run=true`. |
| 72 | + - The workflow builds the gem and provider, shows diffs, and skips pushes/tags/uploads. |
| 73 | +- Local dry-run for the GitHub Actions workflow isn’t practical without a runner like `act`. You can still sanity-check pieces locally: |
| 74 | + - `gem build logstruct.gemspec` |
| 75 | + - `ruby scripts/export_typescript_types.rb` |
| 76 | + - `ruby scripts/export_provider_catalog.rb` |
| 77 | + - `cd terraform-provider-logstruct && go build ./...` |
| 78 | + |
| 79 | +## Required secrets |
| 80 | + |
| 81 | +- `RUBYGEMS_API_KEY`: API key with permission to publish `logstruct`. |
| 82 | +- `PROVIDER_PUSH_TOKEN`: PAT with write access to `DocSpring/terraform-provider-logstruct` for syncing/tagging. |
| 83 | + |
| 84 | +# Core Dependencies |
| 85 | + |
| 86 | +This gem requires Rails 7.0+ and will always have access to these core Rails modules: |
| 87 | + |
| 88 | +- `::Rails` |
| 89 | +- `::ActiveSupport` |
| 90 | +- `::ActionDispatch` |
| 91 | +- `::ActionController` |
| 92 | + |
| 93 | +You do not need to check if these are defined with `defined?` - they are guaranteed to be available. |
| 94 | + |
| 95 | +## Code Style |
| 96 | + |
| 97 | +- NEVER add comments about what you changed (e.g. "this was moved", or "more performant".) |
| 98 | +- NEVER worry about backwards compatibility. This is all brand new code, you must delete old methods and files after refactoring, don't keep them for compatibility. |
| 99 | +- Use strict Sorbet typing with `# typed: strict` annotations |
| 100 | +- You can use `# typed: true` in tests |
| 101 | +- Method signatures must include proper return types |
| 102 | +- Use `::` prefixes for external modules (Rails/third-party gems) |
| 103 | +- `T.must` may be used very sparingly but only in tests - e.g. `T.must(log_file.path)` |
| 104 | +- `T.unsafe` must NEVER be used. Use proper typing or `T.let`/`T.cast` when necessary |
| 105 | +- Don't call `def` inside a method definition in tests (or anywhere). Use mocks or stubs. |
| 106 | +- For modules included in other classes, use `requires_ancestor` |
| 107 | +- Custom type overrides belong in `sorbet/rbi/overrides/` |
| 108 | +- Follow standard Ruby naming conventions: |
| 109 | + - Classes: `CamelCase` |
| 110 | + - Methods/variables: `snake_case` |
| 111 | + - Boolean methods should end with `?` |
| 112 | +- Handle errors explicitly via type-safe interfaces |
| 113 | +- NEVER ignore warnings (especially deprecation warnings) - keep the logs clean |
| 114 | +- When handling objects with as_json method in Rails apps, consider whether ActiveSupport's default implementation or a custom implementation is being used |
| 115 | +- Use minitest mocks and stubs, not `def`, `Object`, etc. |
| 116 | + |
| 117 | +## Code Comments |
| 118 | + |
| 119 | +- Comments should explain why code exists, not what it does |
| 120 | +- Do not reference previous versions/iterations in comments |
| 121 | +- When receiving feedback, incorporate it into the code without mentioning the feedback |
| 122 | +- Never use words like "proper" or "correctly" in comments as they imply previous code was improper |
| 123 | + |
| 124 | +## Development Standards |
| 125 | + |
| 126 | +THERE IS NO RUSH. There is NEVER any need to hurry through a feature or a fix. There are NO deadlines. Never, ever, ever say anything like "let me quickly implement this" or "for now we'll just do this" or "TODO: we'll fix this later" or ANYTHING along those lines. You are a veteran. A senior engineer. You are the most patient and thorough senior engineer of all time. Your patience is unending and your love of high quality code knows no bounds. You take the utmost care and ensure that your code is engineered to the highest standards of quality. You might need to take a detour and refactor a giant method and clean up code as you go. You might notice that some code has been architected all wrong and you need to rewrite it from scratch. This does not concern you at all. You roll up your sleeves and you do the work. YOU TAKE NO SHORTCUTS. AND YOU ALWAYS WRITE TESTS. |
0 commit comments