You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Split the 389-line copilot-instructions.md into a lean 81-line main file
plus 4 scoped instruction files in .github/instructions/:
- testing.instructions.md (applyTo: spec files)
- code-quality.instructions.md (applyTo: *.rb)
- class-structure.instructions.md (applyTo: core class files)
- updater.instructions.md (applyTo: updater/**)
Key improvements:
- Add hard pre-commit checklist (rubocop/srb/rspec must pass before commit)
- Document bin/test --workdir for updater testing
- Document bin/test common for common/ changes
- Add sub-agent validation guidance
- Remove duplicated validation instructions
- Only inject relevant context based on files being edited
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@@ -20,235 +20,15 @@ Each ecosystem implements these 7 required classes that inherit from `dependabot
20
20
-`common/` - Shared base classes and utilities used by all ecosystems
21
21
-`{ecosystem}/` - Each directory contains a complete gem (e.g., `go_modules/`, `bundler/`)
22
22
-`omnibus/` - Meta-gem that includes all ecosystem gems
23
-
-`updater/` - Service layer that orchestrates the update process
23
+
-`updater/` - Service layer that orchestrates the update process (renamed to `dependabot-updater/` inside containers)
24
24
-`script/` - Build and development scripts
25
25
26
-
**Note**: When working in containers, the `updater/` folder is renamed to `dependabot-updater/`. This affects test paths and file references inside the container.
27
-
28
-
## Development Workflow
29
-
30
-
### Local Development Setup
31
-
32
-
```bash
33
-
# Step 1: Start the Docker development environment for a specific ecosystem
# This opens an interactive shell inside the container
36
-
37
-
# Quick command execution (non-CI):
38
-
bin/test {ecosystem} [command]
39
-
# e.g. bin/test uv spec/dependabot/uv/file_updater_spec.rb
40
-
```
41
-
42
-
**Note**: The first run of `bin/docker-dev-shell` can take some minutes as it builds the Docker development image from scratch. Wait for it to complete before proceeding. Check for completion every 5 seconds. Subsequent runs will be much faster as they reuse the built image.
43
-
44
-
### GitHub Actions/CI Environment
45
-
46
-
**For GitHub Actions runners (including Copilot coding agent)**, the interactive `bin/docker-dev-shell` command will NOT work. Instead, use the non-interactive CI pattern:
docker run --rm ghcr.io/dependabot/dependabot-updater-bundler bash -c \
70
-
"cd /home/dependabot && bundle exec srb tc"
71
-
```
72
-
73
-
### Testing Changes
74
-
75
-
**IMPORTANT**: All testing must be done within Docker containers. The development environment, dependencies, and native helpers are containerized and will not work on the host system.
76
-
77
-
For quick one-off runs during local development (outside CI), prefer `bin/test {ecosystem} …` which wraps `bin/docker-dev-shell` and executes the provided command inside the correct container.
78
-
79
-
**Workflow**: First start the container with `bin/docker-dev-shell {ecosystem}`, then run commands within the interactive container shell:
80
-
81
-
```bash
82
-
# Step 1: Start the container (from host)
83
-
bin/docker-dev-shell bundler
84
-
85
-
# Step 2: Run commands inside the container shell
86
-
cd {ecosystem} && rspec spec # Run ecosystem tests
87
-
rubocop # Check code style
88
-
rubocop -A # Auto-fix code style issues (if any found)
89
-
bundle exec srb tc # Run Sorbet type checking
90
-
91
-
# Shortcut: run commands directly without attaching to the shell
# After making changes, run the full validation suite:
101
-
bundle exec tapioca gem --verify # Verify gem type definitions
102
-
bundle exec srb tc # Type check all files
103
-
rubocop # Code style check
104
-
rubocop -A # Auto-fix any code style issues
105
-
rspec spec # Run relevant tests
106
-
```
107
-
108
-
**Test Coverage Requirements**:
109
-
110
-
- All changes must be covered by tests - this is critical to prevent regressions
111
-
- All existing tests must continue to pass after your changes
112
-
- Add tests for new functionality before implementing the feature
113
-
- When fixing bugs, add a test that reproduces the issue first
114
-
-**NEVER test private methods directly** - tests should only call public interfaces
115
-
-**NEVER modify production code visibility to accommodate tests** - if tests need access to private methods, the test design is wrong
116
-
-**NEVER add public methods solely for testing** - this pollutes the production API and creates maintenance burden
117
-
- Tests should verify behavior through public APIs, not implementation details
118
-
- Tests should exercise production code paths (e.g., `fetch_files`) rather than isolated helper methods
119
-
120
-
### Code Style and Validation
121
-
122
-
After making changes, run the full validation suite:
123
-
124
-
```bash
125
-
bundle exec tapioca gem --verify # Verify gem type definitions
126
-
bundle exec srb tc # Type check all files
127
-
rubocop # Code style check
128
-
rubocop -A # Auto-fix any code style issues (if any found)
129
-
rspec spec # Run relevant tests
130
-
```
131
-
132
-
**Important**: Always use `rubocop -A` to automatically fix code style issues when they can be auto-corrected. This ensures consistent formatting and reduces manual work.
133
-
134
-
### RuboCop Best Practices
135
-
136
-
**Avoid adding RuboCop exceptions** unless absolutely necessary. The default approach should be to resolve offenses using proper coding practices:
137
-
138
-
-**Method extraction**: Break large methods into smaller, focused methods
139
-
-**Class extraction**: Split large classes into smaller, single-responsibility classes
140
-
-**Reduce complexity**: Simplify conditional logic and nested structures
141
-
-**Improve naming**: Use clear, descriptive variable and method names
142
-
-**Refactor long parameter lists**: Use parameter objects or configuration classes
143
-
-**Extract constants**: Move magic numbers and strings to named constants
144
-
145
-
**If a RuboCop exception is truly unavoidable**, provide clear justification in a comment explaining why the rule cannot be followed and what alternative approaches were considered.
146
-
147
-
### Sorbet Type Checking
148
-
149
-
**All new files must be Sorbet strict typed at minimum**. When updating existing files with lower typing levels, increase the typing to at least `strict`:
150
-
151
-
```ruby
152
-
# typed: strict
153
-
# frozen_string_literal: true
154
-
```
155
-
156
-
**Typing level requirements**:
157
-
158
-
-**New files**: Must use `# typed: strict` or higher
159
-
-**Existing files**: If below `strict`, upgrade to `# typed: strict` when making changes
160
-
-**Type annotations**: Add explicit type signatures for method parameters and return values
161
-
-**Validation**: Always run `bundle exec srb tc` to ensure type correctness
162
-
163
-
**Sorbet type checking workflow**:
164
-
165
-
```bash
166
-
# Run Sorbet type checker to identify errors
167
-
bundle exec srb tc
168
-
169
-
# Run type checking on specific files to focus on particular issues
170
-
bundle exec srb tc path/to/file.rb
171
-
172
-
# Use autocorrect ONLY when you have high confidence it won't cause issues
173
-
bundle exec srb tc -a path/to/file.rb
174
-
```
175
-
176
-
**Important**: Sorbet's autocorrect feature (`-a` flag) should be used cautiously as it can cause more issues than it resolves. Only use autocorrect when you have high confidence that the changes will not break code functionality.
177
-
178
-
Autocorrect can handle some simple cases like:
179
-
- Adding missing `override.` annotations for method overrides
180
-
- Adding `T.let` declarations for instance variables in strict-typed files
181
-
- Adding type annotations for constants
182
-
183
-
However, autocorrect often creates incorrect fixes for complex type mismatches, method signature issues, and structural problems. **Always manually resolve Sorbet errors** rather than relying on autocorrect, and carefully review any autocorrected changes to ensure they maintain code correctness and intent.
184
-
185
-
### Code Comments and Documentation
186
-
187
-
**Prioritize self-documenting code over comments**. Write clear, intention-revealing code with descriptive method and variable names that eliminate the need for explanatory comments.
188
-
189
-
**When to use comments**:
190
-
-**Business logic context**: Explain *why* something is done when the reason isn't obvious from the code
191
-
-**Complex algorithms**: Document the approach or mathematical concepts
192
-
-**Workarounds**: Explain why a non-obvious solution was necessary
193
-
-**External constraints**: Document API limitations, system requirements, or ecosystem-specific behaviors
194
-
-**TODO/FIXME**: Temporary markers for future improvements (with issue references when possible)
195
-
196
-
**Avoid these comment types**:
197
-
-**Implementation decisions**: Don't explain what was *not* implemented or alternative approaches considered
198
-
-**Obvious code explanations**: Don't restate what the code clearly does
-**Outdated information**: Remove comments that no longer apply to current implementation
201
-
-**Version history**: Use git history instead of inline change logs
202
-
203
-
**Comment style guidelines**:
204
-
```ruby
205
-
# Good: Explains WHY, adds business context
206
-
# Retry failed requests up to 3 times due to GitHub API rate limiting
207
-
retry_count =3
208
-
209
-
# Bad: Explains WHAT the code does (obvious from code)
210
-
# Set retry count to 3
211
-
retry_count =3
212
-
213
-
# Good: Documents external constraint
214
-
# GitHub API requires User-Agent header or returns 403
215
-
headers['User-Agent'] ='Dependabot/1.0'
216
-
217
-
# Bad: Implementation decision discussion
218
-
# We decided not to cache this because it would complicate the code
219
-
# and other ecosystems don't do caching here either
220
-
response = fetch_data(url)
221
-
```
222
-
223
-
**Prefer code refactoring over explanatory comments**:
224
-
```ruby
225
-
# Instead of commenting complex logic:
226
-
# Calculate the SHA256 of downloaded file for security verification
227
-
digest =Digest::SHA256.hexdigest(response.body)
228
-
229
-
# Extract to a well-named method:
230
-
defcalculate_security_checksum(content)
231
-
Digest::SHA256.hexdigest(content)
232
-
end
233
-
```
234
-
235
-
### Native Helpers
236
-
237
-
Many ecosystems use native language helpers (Go, Node.js, Python) located in `{ecosystem}/helpers/`. These helpers run exclusively within containers and changes require rebuilding:
238
-
239
-
```bash
240
-
# Inside dev container - native helpers only work in containerized environment
When implementing new ecosystems or modifying existing ones, always ensure the 7 core classes are implemented and follow the established inheritance patterns from `dependabot-common`.
329
-
330
-
## Core Class Structure Pattern
62
+
When implementing or modifying ecosystems, ensure the 7 core classes are implemented and follow the inheritance patterns from `dependabot-common`.
331
63
332
-
**CRITICAL**: All Dependabot core classes with nested helper classes must follow the exact pattern to avoid "superclass mismatch" errors. This pattern is used consistently across all established ecosystems (bundler, npm_and_yarn, go_modules, etc.).
333
-
334
-
### Main Class Structure (applies to FileFetcher, FileParser, FileUpdater, UpdateChecker, etc.)
Support private registry credentials through the credential proxy pattern — never store credentials in Dependabot Core directly.
369
73
370
-
### Key Rules:
371
-
1.**Main classes** inherit from appropriate base: `Dependabot::FileUpdaters::Base`, `Dependabot::FileFetchers::Base`, etc.
372
-
2.**Helper classes** are nested inside the main class
373
-
3.**require_relative** statements go INSIDE the main class, not at module level
374
-
4.**Helper classes require the main file** first: `require "dependabot/{ecosystem}/file_updater"`
375
-
5.**Never define multiple top-level classes** with same name in the same namespace
376
-
6.**Backward compatibility** can use static methods that delegate to instance methods
74
+
### Cross-Platform
377
75
378
-
### Applies To:
379
-
-**FileFetcher** and its helpers (e.g., `FileFetcher::GitCommitChecker`)
380
-
-**FileParser** and its helpers (e.g., `FileParser::ManifestParser`)
381
-
-**FileUpdater** and its helpers (e.g., `FileUpdater::LockfileUpdater`)
382
-
-**UpdateChecker** and its helpers (e.g., `UpdateChecker::VersionResolver`)
383
-
-**MetadataFinder** and its helpers
384
-
-**Version** and **Requirement** classes (if they have nested classes)
76
+
- Use `SharedHelpers.in_a_temporary_repo_directory` for file operations
77
+
- Native helpers must support the container's architecture
385
78
386
79
## Adding New Ecosystems
387
80
388
-
If you are adding a new ecosystem, follow the detailed guide in `./NEW_ECOSYSTEMS.md`which provides step-by-step instructions for implementing a new package manager ecosystem.
81
+
Follow the detailed guide in `./NEW_ECOSYSTEMS.md`for step-by-step instructions on implementing a new package manager ecosystem.
0 commit comments