- ALWAYS push branches to
DataDog/dd-trace-rb, not forks - ALWAYS use
--repo DataDog/dd-trace-rbwith gh commands (defaults are unreliable) - PR descriptions MUST use
.github/PULL_REQUEST_TEMPLATE.mdas the starting point - Write for the developer performing code review; be concise
- Use one sentence per relevant point in summary/motivation sections
- Changelog entries are written for customers only; consider changes from user/customer POV
- Internal changes (telemetry, CI, tooling) = "None" for changelog
- Changelog entry format: MUST start with "Yes." or "None."
- If changes need CHANGELOG:
Yes. Brief customer-facing summary. - If no CHANGELOG needed:
None. - Never write just the summary without "Yes." prefix
- If changes need CHANGELOG:
- Add
--label "AI Generated"when creating PRs (do not mention AI in description; label is sufficient)
- Use
git commit --amendunless the user explicitly and clearly requests it (always create new commits by default) - Push commits to remote (
git push) unless the user explicitly requests it - Commit secrets, tokens, or credentials
- Edit files under
gemfiles/(auto-generated; usebundle exec rake dependency:generate) - Change versioning (
lib/datadog/version.rb,CHANGELOG.md) - Leave resources open (terminate threads, close files)
- Make breaking public API changes
- Use
sleepin tests for synchronization (use deterministic waits: Queue, ConditionVariable, flush methods that block, or mock time)
- Modifying dependencies in
datadog.gemspec,appraisal/, orMatrixfile - Editing CI workflows or release automation
- Touching vendored third-party code (except
vendor/rbs) - Modifying
@public_apiannotated code (readdocs/PublicApi.mdfirst)
When creating or modifying workflows in .github/workflows/:
- NEVER interpolate user input directly in
run:blocks - useenv:instead:# BAD: run: echo "${{ github.event.comment.body }}" # GOOD: env: COMMENT: ${{ github.event.comment.body }} run: echo "$COMMENT"
- User-controllable inputs:
github.event.comment.body,github.event.issue.title,github.event.pull_request.title,github.head_ref - Pin actions to SHA:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - Set
permissions: {}at workflow level; explicit minimal permissions per job - Prefer
pull_requestoverpull_request_target
- Always quote variables:
"$VAR"not$VAR - Quote
$GITHUB_OUTPUT:echo "key=value" >> "$GITHUB_OUTPUT" - Group multiple redirects:
{ echo "a"; echo "b"; } >> "$GITHUB_OUTPUT" - Avoid heredocs; use echo grouping instead
yamllint --strict .github/workflows/your-workflow.yml
actionlint .github/workflows/your-workflow.yml- Read files before editing them
- When user says "suggest" or asks a question: analyze only, do not modify code
- When user says "fix", "change", "update": make the changes
- If a requested change contradicts code evidence, alert user before proceeding
- If unable to access a requested web page, explicitly state this and explain basis for any suggestions
- Use
Core::Utils::Array.filter_mapinstead offilter_mapfor compatibility with Ruby 2.5 and 2.6 (nativefilter_maprequires Ruby 2.7+) - Use
Datadog::Core::Utils::Time.nowinstead ofTime.noweverywhere — the time provider is configurable (e.g. for Timecop support) and tests can override it viaCore::Utils::Time.now_provider=- Exception: constants initialized at load time (before user configuration) may use
::Time.nowdirectly; add a comment explaining why (seelib/datadog/profiling/collectors/info.rbfor an example) - Exception: Dynamic Instrumentation (DI) probe instrumentation code that runs inside customer application methods must use
::Time.nowdirectly — the time provider supports runtime overrides (the API exists even if rarely used in production), and DI must never invoke customer-provided code during instrumentation
- Exception: constants initialized at load time (before user configuration) may use
- Dynamic Instrumentation docs: Never mention telemetry in customer-facing documentation (e.g.,
docs/DynamicInstrumentation.md)- Telemetry is internal and not accessible to customers
- Only mention observable behavior (logging, metrics visible to customers)
- Internal code comments may mention telemetry when describing implementation
- Use
DATADOG_ENV, neverENVdirectly (seedocs/AccessEnvironmentVariables.md) - Run
rake local_config_map:generatewhen adding new env vars
See AGENTS.md for:
- Project structure and directory layout
- Docker container setup (
docker compose run --rm tracer-3.4 /bin/bash) - Bundle, rake, and rspec commands
- Integration patterns (
patcher.rb,integration.rb,ext.rb,configuration/settings.rb)
See docs/ for:
DevelopmentGuide.md- detailed development workflowsGettingStarted.md- user-facing documentation (update when adding settings/env vars)StaticTypingGuide.md- RBS and Steep usagePublicApi.md- public API guidelines
bundle exec rake test:main # Smoke tests
bundle exec rake standard typecheck # Lint and type check
bundle exec steep check [sources] # Type check (sources = files or dirs, optional)
bundle exec rspec spec/path/file_spec.rb:123 # Run specific test- Pipe rspec output:
2>&1 | tee /tmp/rspec.log | grep -E 'Pending:|Failures:|Finished' -A 99 - Transport noise (
Internal error during Datadog::Tracing::Transport::HTTP::Client request) is expected - Profiling specs fail on macOS without additional setup
ProbeNotifierWorker#flushblocks until queues are empty - never addsleepafter it
Enforced by StandardRB: bundle exec rake standard:fix
Additional team preferences:
- Trailing commas in multi-line arrays, hashes, and arguments
- RBS type definitions in
sig/mirrorlib/structure - Avoid
untyped; useType?not(nil | Type)