Skip to content

Add CircleCI as a CI provider for JavaScript and Ruby - #254

Merged
juan-fernandez merged 8 commits into
mainfrom
juan-fernandez/circleci-provider
Oct 29, 2026
Merged

juan-fernandez merged 8 commits into
mainfrom
juan-fernandez/circleci-provider

Conversation

@juan-fernandez

Copy link
Copy Markdown
Contributor

What

Adds CircleCI as a CI provider for JavaScript and Ruby, on the same seam as GitLab (#249).

  • Discovery. ddtest reads .circleci/config.yml: executors, commands and parameters, matrix jobs, conditional steps and workflows, $BASH_ENV exports, and the common circleci tests split/run forms. Unknown orb commands, dynamic config (setup: true) and anything else it can't resolve are reported, never dropped. Notification, scanning and coverage orbs (slack, jira, snyk, sonarcloud, codecov, coveralls) are caveats.
  • Setup. CI setup uses Datadog's official orb (datadog/test-optimization-circleci-orb@2).
    • JavaScript: onboard --apply adds the orb declaration and the autoinstrument step before the tests.
    • Ruby: the agent adds the step through ci_setup_required.
    • Missing key: the orb fails the job when DD_API_KEY isn't set, and the instructions and human action say so, including forked-PR builds and restricted contexts.
  • Complete setup. One shared check: the orb step runs unconditionally before the tests, at @2 or an exact @2.x.y, with the language in languages, an exact tracer version and the selected site.
  • Images. Jobs on images without Bash (the orb exports through $BASH_ENV), slim images without curl, or unresolved images are reported, not set up. Ruby versions come from images such as cimg/ruby:3.3.
  • Other languages. Python and Java answer ci_provider_unsupported on CircleCI.
  • Shared with GitLab. The shell-state follower and image checks are now shared with GitLab. GitHub and GitLab output is unchanged.

Why

Customers whose tests run on CircleCI couldn't onboard with ddtest. Using Datadog's orb keeps CI setup on the supported installer the GitHub action and the GitLab script also use.

E2E testing

Prerequisites:

  • this branch built as ddtest;
  • Node 22+ and npm;
  • Ruby 3.2+ with Bundler, and the datadog-ci 1.42.0, rspec and rake gems.

Copy each fixture into a fresh git repository (git init -q && git add -A), and keep the same shell, including TMPDIR, between a run and its --report.

  1. JavaScript: copy internal/onboard/testdata/circleci-javascript (based on marp-vscode's config), then run npm install.
    • ddtest onboard --agent. Expected: ready.
    • ddtest onboard --framework jest --apply --yes --tracer-version 5.133.0 --format json. Expected: complete_locally. .circleci/config.yml gets the orb declaration and an autoinstrument step before the tests, and .gitignore gets /.testoptimization/.
    • Run the same --apply again without --yes. Expected: "Jest CI setup is already configured; no edits."
    • ddtest testdrive --all --agent --yes, then ddtest testdrive --report. Expected:
      • complete_locally and "Executed Jest validations: PASSED (1/1)";
      • a human action to add DD_API_KEY in CircleCI, saying the job fails without it;
      • a caveat for the coverage orb.
  2. Alpine image: in the JavaScript copy, change the job image to node:22-alpine and run the --apply --yes command again. Expected: ci_edit_required, saying the image has no Bash so the orb step can't run.
  3. Ruby: copy internal/onboard/testdata/circleci-ruby (based on rubyXL's config), then run bundle install.
    • ddtest onboard --agent. Expected: ci_setup_required, with orb instructions and the RubyGems guard for the Ruby 3.0 entry.
    • Add the orb declaration, the guard and the autoinstrument step (languages: ruby, ruby_tracer_version: 1.42.0), and /.testoptimization/ to .gitignore. Then run ddtest onboard --agent twice. Expected: ready both times.
    • ddtest testdrive --framework rspec --all --agent --yes, then --report. Expected: complete_locally and "PASSED (1/1)".
    • Set ruby_tracer_version: latest. Expected: onboard --agent returns ci_setup_required. Declaring the orb at @1 instead makes check-only report "not a supported release".
  4. Three providers: use a Jest repo where GitHub Actions, GitLab CI and CircleCI all run tests.
    • ddtest onboard --agent. Expected: ci_provider_required, required_input: [github, gitlab, circleci].
    • With --ci-provider circleci. Expected: ready.
  5. Python: in a pytest repo with only .circleci/config.yml, run ddtest onboard --agent. Expected: ci_provider_unsupported.

Cleanup: delete the scratch repositories.

🤖 Generated with Claude Code

@datadog-official

datadog-official Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Pipelines  Tests

⏳ PR checks are still running. This summary will update when all results arrive.

🎉 All green!

🧪 All tests passed

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 60ea844 | Docs | View more details | Give us feedback!

@juan-fernandez

Copy link
Copy Markdown
Contributor Author

/datadog autotest review
@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-29T12:20:14.289498Z 17b4d76 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5460bc253c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@datadog-official datadog-official Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bits Code Review: FAIL

CircleCI onboarding can produce a configuration that CircleCI rejects when the input uses version 2. Validation can also omit test commands or certify instrumentation that conditional exports and non-Bash test steps do not load.

Open Bits AI session

🤖 Bits Code Review · Commit 5460bc2

@juan-fernandez

Copy link
Copy Markdown
Contributor Author

/datadog autotest review
@codex review

@juan-fernandez
juan-fernandez marked this pull request as ready for review October 29, 2026 09:09
@juan-fernandez
juan-fernandez requested a review from a team as a code owner October 29, 2026 09:09

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1fac4f99fa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/testdrive/jest.go Resolved

@datadog-official datadog-official Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bits Code Review: FAIL

CircleCI setup can be inserted before a test step using sh, leaving tests uninstrumented. Runtime tracking can also check the wrong version, while failure normalization can hide differences between baseline and instrumented failures.

Open Bits AI session

🤖 Bits Code Review · Commit 1fac4f9

Comment thread internal/onboard/runtime.go Resolved
Comment thread internal/testdrive/jest.go Resolved

@datadog-official datadog-official Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bits Code Review: FAIL

CircleCI validation can skip valid suites, trust stale runtime and preload state, or select different tests through command rewriting. Failure normalization also hides legitimate hexadecimal assertion differences.

Open Bits AI session

🤖 Bits Code Review · Commit 1fac4f9

Comment thread internal/onboard/runtime.go Resolved
Comment thread internal/testdrive/jest.go Resolved
@juan-fernandez
juan-fernandez force-pushed the juan-fernandez/circleci-provider branch from 175b64d to 65e1d33 Compare October 29, 2026 11:02
@juan-fernandez

Copy link
Copy Markdown
Contributor Author

/datadog autotest review
@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 65e1d3379e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/testdrive/repeatability.go Resolved

@datadog-official datadog-official Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bits Code Review: FAIL

CircleCI discovery can silently omit repeated job invocations and tests in orb hooks. Shell-state handling can also validate different suites or Ruby options from CI and accept an installer whose curl dependency is conditional.

Open Bits AI session

🤖 Bits Code Review · Commit 65e1d33

Comment thread internal/onboard/ruby.go Resolved
@juan-fernandez

Copy link
Copy Markdown
Contributor Author

/datadog autotest review
@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17b4d76eee

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/onboard/ruby.go Resolved

@datadog-official datadog-official Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bits Code Review: FAIL

Inline Ruby exports can hide a removed Datadog preload or replay different environment values from CI. CircleCI setup also skips supported jobs that install a newer Node runtime over an unsupported image runtime.

Open Bits AI session

🤖 Bits Code Review · Commit 17b4d76

Comment thread internal/onboard/ruby.go Resolved
Comment thread internal/onboard/apply_runtime.go Resolved
Comment thread internal/onboard/ruby.go Resolved
Comment thread internal/onboard/ruby.go Resolved
juan-fernandez and others added 8 commits October 29, 2026 14:23
ddtest now reads .circleci/config.yml into the shared workflow model
(executors, reusable commands, parameters, inline orbs, matrix, when/unless,
$BASH_ENV, test splitting) and sets up Test Optimization with Datadog's
Test Optimization orb. JavaScript setup is applied by onboard --apply;
Ruby setup is applied by the coding agent from onboard --agent. Python and
Java answer ci_provider_unsupported on CircleCI.

The shell-state follower, image checks and setup-note wording that GitLab
CI introduced are now shared by both providers.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Read circleci/node, circleci/ruby and circleci/browser-tools orbs from
  models of their source, provided through a language hook
  (ciComponents): installs are preparation, install commands select the
  runtime, node/test, node/run and ruby/rspec-test run the commands they
  run, rubocop-check only lints. Other commands and releases stay
  unresolved.
- Treat diagnostic prints (npm --version) and type checkers (tsd) before
  the tests as outside the test path on every provider.
- Compare test failures without object addresses, so the same failure in
  every run is not reported as varying outcomes.
- Report Qlty's coverage upload orb as a non-test orb.
- Report a rake RUBYOPT=... argument that replaces the Datadog preload.
- Move version 2 configurations to 2.1 when applying the orb, and report
  orbs declared in a version 2 configuration.
- Follow override-with, anchor matches conditions, type condition values,
  substitute plain $BASH_ENV assignments into later commands, reject
  compound test-splitting commands, keep $BASH_ENV away from sh steps and
  leave $BASH_ENV changes under undecided conditions unresolved.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…er choice, tracer

- Report tests whose names only one run reports as
  unstable_test_identities, with the offending examples and the static
  description fix, instead of varying outcomes.
- Resolve Ruby test steps that export literal variables, run exactly one
  test command (a rake RUBYOPT="$RUBYOPT ..." argument joins the preload)
  and then only move, copy or print artifacts.
- Don't count documentation tooling run through bundle exec (yard, rdoc)
  as possible JavaScript tests, so workflows that only build docs don't
  make a provider a candidate.
- When the latest tracer can't run on every instrumented CI row and no
  release passes the framework's support check, select the newest release
  that runs on every row, say so, and report its support gap.
- Add the ksylvest/omniai fixture.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ll checks

Discovery's variant expansion rejected a literal export and a $RUBYOPT
read, so brakeman's fixed test-3-2 step (export, then
rake RUBYOPT="$RUBYOPT ...") still needed separate CI setup. Reads of the
variables the installer exports stay as written for the language's
resolver, and literal exports pass through. Setup also says which tracer
the CI rows' recommendation selected.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…nd runtimes

- Normalize object addresses only inside object representations (Ruby
  #<Foo:0x...>, Python <x object at 0x...>, Java pkg.Class@hash), so
  differing bare hexadecimal values still differ.
- Substitute $BASH_ENV shell variables only where Bash expands them,
  reading the shell syntax tree: never inside single quotes or escapes,
  escaped inside double quotes, unresolved with expansion operators.
- Follow $BASH_ENV writes in steps that also run other commands, and make
  later steps unresolved after a write ddtest cannot follow.
- Check later tests against the Node a modeled node/install selects.
- Leave the runtime unknown when a modeled installer runs under a
  condition ddtest cannot decide.
- Refuse to insert the orb before a test step that runs with /bin/sh.
- Extract the split-test command with the shell parser, keeping quoted
  arguments as written.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…inline rake RUBYOPT

- An unstable_test_identities verdict lists each affected example once,
  whatever names the runs gave it, up to 50, and counts the rest.
- A gemspec whose files are an allowlist of specific paths
  (Dir.glob("{bin,lib,exe}/**/*") + %w[README.md Gemfile]) can't include
  .testoptimization/: the guidance says not to edit it.
- When a CI test command passes RUBYOPT as a rake argument, the Ruby
  handoff prescribes RUBYOPT="$RUBYOPT <options>" for it on every
  provider.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…idation

- Leave reads of a variable the step itself assigns earlier as written,
  instead of substituting the value an earlier step put in $BASH_ENV;
  read/unset/for on such variables stay unresolved.
- Diagnose unstable test identities only when the one-off names are one
  example's variants (after stripping generated values and framework
  truncation); disjoint stable names stay varying outcomes. The report
  keeps every listed example instead of 10.
- Keep both invocations when a workflow runs one job twice under the same
  name, and report the clash CircleCI rejects.
- A rake RUBYOPT="$RUBYOPT ..." argument keeps the options the step
  inherits and adds its own.
- Make a step unresolved when it sets a variable that text appended to
  $BASH_ENV reads, since Bash re-evaluates that text in each step.
- Count a curl install toward the orb's downloader check only when it
  certainly runs.
- Read workflow hooks on a non-test orb's job as the configuration's steps.
- After a retried run completes, name the tests earlier attempts saw vary
  as a caveat in the final response.
- Classify jobs that never run the framework before recording their
  preparation, so a build-only job is a caveat, not a blocker.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Leave Ruby test steps unresolved when they export RUBYOPT or a Datadog
  setting, or append to a variable; decode escapes in exported values.
- Treat commands after the test as artifact handling only when they touch
  report, coverage or test-result paths; copying other files may prepare a
  later test.
- Substitute $BASH_ENV variables only after top-level, unconditional
  assignments of the step; an assignment in a subshell, function or
  condition leaves the step unresolved.
- Select CircleCI setup targets on the Node a modeled installer selects
  before the tests, not only the image's.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@juan-fernandez
juan-fernandez force-pushed the juan-fernandez/circleci-provider branch from 17b4d76 to 60ea844 Compare October 29, 2026 13:28
@juan-fernandez
juan-fernandez merged commit 41f401a into main Oct 29, 2026
121 checks passed
@juan-fernandez
juan-fernandez deleted the juan-fernandez/circleci-provider branch October 29, 2026 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants