Skip to content

feat(chroma): update to chroma 1.x#3552

Merged
mdelapenya merged 6 commits intotestcontainers:mainfrom
amikos-tech:feat/chroma-go-v0.3.2-update
Feb 6, 2026
Merged

feat(chroma): update to chroma 1.x#3552
mdelapenya merged 6 commits intotestcontainers:mainfrom
amikos-tech:feat/chroma-go-v0.3.2-update

Conversation

@tazarov
Copy link
Copy Markdown
Contributor

@tazarov tazarov commented Feb 6, 2026

What does this PR do?

Updates the Chroma module from chromadb/chroma:0.4.24 to chromadb/chroma:1.4.0 and bumps chroma-go from v0.1.2 to v0.3.2.

Chroma 1.x ships a v2 REST API, so this PR:

  • Switches the client import from github.com/amikos-tech/chroma-go to github.com/amikos-tech/chroma-go/pkg/api/v2
  • Changes the heartbeat wait strategy to /api/v2/heartbeat and drops the wait.ForLog("Application startup complete") check (Chroma 1.x no longer emits that log)
  • Rewrites tests and examples for the new NewHTTPClient/WithBaseURL constructor and updated method signatures
  • Adds v1-config.yaml so the collections example can set allow_reset: true (Chroma 1.x reads config from a YAML file instead of env vars)
  • Adds Close() calls to clean up client resources

Why is it important?

The module was pinned to Chroma 0.4.x, which is no longer maintained. Chroma 1.x changed the REST API and Go client in backwards-incompatible ways, so the module stopped working against current Chroma releases.

Related issues

N/A

@tazarov tazarov requested a review from a team as a code owner February 6, 2026 09:01
@netlify
Copy link
Copy Markdown

netlify bot commented Feb 6, 2026

Deploy Preview for testcontainers-go ready!

Name Link
🔨 Latest commit 498325c
🔍 Latest deploy log https://app.netlify.com/projects/testcontainers-go/deploys/6985bf9c9430b90007d89c5d
😎 Deploy Preview https://deploy-preview-3552--testcontainers-go.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 6, 2026

Summary by CodeRabbit

  • Dependencies

    • Updated Chroma container to 1.4.0 and bumped chroma-go and Go toolchain/dependency versions.
  • Documentation

    • Examples and docs refreshed for the v2 API and updated client usage.
  • Examples / Tests

    • Tests and examples adjusted for the new client lifecycle, heartbeat endpoint behavior, and updated collection/query/result interfaces.
  • Chores

    • Added a sample v1 configuration file for local testing.

Walkthrough

Upgrade Chroma integration to chromadb/chroma:1.4.0 and chroma-go v0.3.2 (API v2): update Docker image, heartbeat endpoint, client initialization and lifecycle, collection/add/query APIs, tests, examples, and module dependencies.

Changes

Cohort / File(s) Summary
Docs & Examples
docs/modules/chroma.md, modules/chroma/examples_test.go
Bumped Chroma image to chromadb/chroma:1.4.0; changed imports to github.com/amikos-tech/chroma-go/pkg/api/v2; switched client creation to NewHTTPClient(chromago.WithBaseURL(...)); updated collection create/add/query APIs and added explicit Close() lifecycle handling; added host-bind mounts in tests.
Core module & tests
modules/chroma/chroma.go, modules/chroma/chroma_test.go
Updated container image to chromadb/chroma:1.4.0; replaced log-based startup wait with HTTP heartbeat at /api/v2/heartbeat; adjusted client creation and test cleanup to use chroma-go v2 client and Close().
Dependencies
modules/chroma/go.mod
Bumped go directive (1.24.0 → 1.24.11); upgraded github.com/amikos-tech/chroma-go to v0.3.2; updated/added multiple indirect dependencies (validator, onnxruntime_go, OpenTelemetry, etc.).
Test config
modules/chroma/testdata/v1-config.yaml
Added YAML config with HTTP server settings (port: 8000, listen_address: "0.0.0.0") and general settings (persist_path: /data, allow_reset: true).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐇 I hopped to a newer, brighter stream,

Containers woke to a v2 dream,
Clients connect and politely close,
Collections hum where metadata grows,
A tiny hop — the codebase gleams.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(chroma): update to chroma 1.x' directly and concisely summarizes the main change of upgrading the Chroma module from version 0.4.x to 1.x.
Description check ✅ Passed The description clearly explains what the PR does, why it matters, and lists the specific changes made to support Chroma 1.x including API updates, new client constructors, and configuration changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@modules/chroma/examples_test.go`:
- Around line 221-225: The example test currently hardcodes the float distance
"0.7525849" in the Output block which is brittle; change the test to assert the
returned distance using a tolerance instead of exact string matching (e.g.,
compare the numeric distance from the query result with math.Abs(result.Distance
- expected) < tol) and update or remove the exact float in the Output comment;
look for the example that prints "Result of query" in
modules/chroma/examples_test.go and replace the strict equality check /
expected-output line with a tolerance-based numeric assertion referencing the
query result variable (e.g., result.Distance) and a small tolerance (e.g.,
1e-3).
🧹 Nitpick comments (5)
modules/chroma/chroma_test.go (1)

43-45: Unnecessary defer inside t.Cleanup, and should use tt (subtest *testing.T).

Two things:

  1. The defer inside t.Cleanup is redundant — the function body only calls Close(), so defer adds no value. Just call chromaClient.Close() directly.
  2. This uses t (parent test) instead of tt (subtest). The cleanup will run when the outer TestChroma finishes rather than when the "GetClient" subtest finishes. Use tt.Cleanup to scope the lifecycle correctly.
Proposed fix
-		t.Cleanup(func() {
-			defer chromaClient.Close()
-		})
+		tt.Cleanup(func() {
+			chromaClient.Close()
+		})
modules/chroma/examples_test.go (3)

214-219: defer Close() should be placed immediately after successful client creation.

The defer chromaClient.Close() is placed at the very end of the function (line 214), after all collection operations. If any operation between client creation (line 123) and here panics, the client leaks. Move it right after the error check on line 128.

Proposed fix — move Close() defer right after client creation

Place this block right after line 128 (return after failed client creation):

	defer func() {
		err = chromaClient.Close()
		if err != nil {
			log.Printf("failed to close client: %s", err)
		}
	}()

And remove lines 214–219.


72-82: Same late-defer pattern here — Close() should follow client creation.

The defer Close() at lines 77–82 should be placed immediately after verifying client creation succeeded (after line 70), not after the heartbeat call. In example code this also serves as a best-practice demonstration for users.

Proposed fix
 	chromaClient, err := chromago.NewHTTPClient(chromago.WithBaseURL(endpoint))
 	if err != nil {
 		log.Printf("failed to get client: %s", err)
 		return
 	}
+	// closeClient {
+	// ensure all resources are freed, e.g. TCP connections or the default embedding function which runs locally
+	defer func() {
+		err = chromaClient.Close()
+		if err != nil {
+			log.Printf("failed to close client: %s", err)
+		}
+	}()
+	// }
 
 	errHb := chromaClient.Heartbeat(context.Background())
-	// }
 	fmt.Println(errHb) // error is only returned if the heartbeat fails
-	// closeClient {
-	// ensure all resources are freed, e.g. TCP connections or the default embedding function which runs locally
-	defer func() {
-		err = chromaClient.Close()
-		if err != nil {
-			log.Printf("failed to close client: %s", err)
-		}
-	}()
-	// }

96-103: Minor: simplify mount slice construction.

Proposed simplification
 		testcontainers.WithHostConfigModifier(func(hostConfig *container.HostConfig) {
-			dockerMounts := make([]mount.Mount, 0)
-			dockerMounts = append(dockerMounts, mount.Mount{
+			hostConfig.Mounts = []mount.Mount{{
 				Type:   mount.TypeBind,
 				Source: filepath.Join(cwd, "v1-config.yaml"),
 				Target: "/config.yaml",
-			})
-			hostConfig.Mounts = dockerMounts
+			}}
 		}),
modules/chroma/go.mod (1)

6-7: Direct dependency on docker/docker added for host config modifier usage in examples.

The examples_test.go file directly imports container and mount types from github.com/docker/docker to configure bind mounts via WithHostConfigModifier. While this works, testcontainers-go provides higher-level helpers (WithMounts, WithFiles) that could potentially simplify this and reduce the direct Docker SDK dependency in examples. Consider whether these alternatives could replace the current WithHostConfigModifier approach for mounting the configuration file.

Comment thread modules/chroma/examples_test.go Outdated
Replace brittle exact float comparison with tolerance check to avoid
CI failures from platform-dependent floating point precision differences.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@modules/chroma/examples_test.go`:
- Around line 96-106: The example launches Chroma via chroma.Run and currently
passes an ALLOW_RESET env var while also mounting v1-config.yaml which already
sets allow_reset: true; remove the redundant WithEnv map entry for "ALLOW_RESET"
from the chroma.Run call (i.e., drop
testcontainers.WithEnv(map[string]string{"ALLOW_RESET": "true"})) or, if you
choose to keep it, add a short comment next to the chromaContainer/chroma.Run
invocation explaining that Chroma 1.x reads allow_reset from v1-config.yaml and
the environment variable is unnecessary and may be ignored to avoid misleading
users.
🧹 Nitpick comments (2)
modules/chroma/examples_test.go (2)

216-221: Move defer chromaClient.Close() immediately after successful client creation.

Currently, Close() is deferred at line 216, but the client is created at line 124. Any early return between lines 129–215 (there are ~6 such paths) will skip registering the defer and leak client resources (e.g., TCP connections, local embedding function).

♻️ Proposed fix

Move the defer block right after the client error check:

 	chromaClient, err := chromago.NewHTTPClient(chromago.WithBaseURL(endpoint))
 	// }
 	if err != nil {
 		log.Printf("failed to get client: %s", err)
 		return
 	}
+	defer func() {
+		err = chromaClient.Close()
+		if err != nil {
+			log.Printf("failed to close client: %s", err)
+		}
+	}()
 	// reset {

And remove the defer block at lines 216–221.


159-166: Remove commented-out code from example.

Lines 160 and 184 contain commented-out options (WithIDGenerator, WithInclude). Since this is user-facing example code meant to be copied, leaving dead comments can be confusing. Either remove them or convert to explanatory comments if the intent is to show alternative usage.

Comment thread modules/chroma/examples_test.go Outdated
The mounted v1-config.yaml already sets allow_reset: true, making the
env var unnecessary for Chroma 1.x.
@tazarov tazarov changed the title feat(chroma): Update to chroma 1.x feat(chroma): update to chroma 1.x Feb 6, 2026
Comment thread modules/chroma/examples_test.go Outdated
Replace WithHostConfigModifier bind mount with testcontainers.WithFiles
for better reproducibility. Move v1-config.yaml to testdata directory.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@modules/chroma/examples_test.go`:
- Around line 204-209: The defer that calls chromaClient.Close() is registered
too late and won't run if any early return happens; immediately after creating
and validating chromaClient (right after the error check that follows the client
construction/assignment), add a deferred closure that calls chromaClient.Close()
and logs any error (i.e., defer func() { if err := chromaClient.Close(); err !=
nil { log.Printf("failed to close client: %s", err) } }()), and remove the later
deferred block that currently appears around lines 204–209 so Close() runs even
on early returns.
- Around line 89-94: The ContainerFile passed into chroma.Run (the
testcontainers.ContainerFile literal in the chromaContainer creation) is missing
FileMode and thus creates a no-permission file; update that ContainerFile to
include FileMode: 0o644 so the container can read /config.yaml (modify the
ContainerFile used in the chroma.Run call).
🧹 Nitpick comments (2)
modules/chroma/examples_test.go (2)

73-81: Consider placing defer Close() immediately after successful client creation.

The defer chromaClient.Close() is registered at the very end of the function. If future edits add an early return between client creation (line 64) and here, the client won't be closed. Moving the defer right after the error check on line 68 is the idiomatic Go pattern.

That said, I see this is grouped in a // closeClient { documentation section — if preserving that marker placement is important for doc generation, this is acceptable as-is.


147-154: Remove commented-out code from example functions.

Lines 148 and 172 contain commented-out API calls. In example code that users copy, these are confusing — either include them with a clear explanation or remove them entirely. If they're meant as documentation hints, consider adding them to the module's doc page instead.

Comment thread modules/chroma/examples_test.go
Comment thread modules/chroma/examples_test.go Outdated
…r early

Set FileMode 0o644 on the copied config file so the container can read
it. Move chromaClient.Close() defer immediately after client creation
to ensure cleanup on early returns.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@modules/chroma/examples_test.go`:
- Around line 153-160: Remove the stale commented-out snippet and any references
to undefined symbols: delete the commented
chroma.WithIDGenerator(chroma.NewULIDGenerator()) line inside the col.Add(...)
call and ensure you do not reference non-imported/undefined types like
types.IDocuments; if you intended to use chroma-go symbols, replace any
accidental "chroma." references with the correct "chromago." identifiers (e.g.,
use chromago's ID generator API) and/or remove the erroneous import/use so the
example compiles cleanly.
🧹 Nitpick comments (1)
modules/chroma/examples_test.go (1)

187-188: Consider splitting this long line for readability in example code.

At ~170 characters, this line packs a lot of logic (index access, type conversion, tolerance check, and format string) into a single fmt.Printf. For documentation examples that users will reference, splitting it would improve clarity.

♻️ Suggested split
-	distance := queryResults.GetDistancesGroups()[0][0]
-	fmt.Printf("Result of query: %v %v distance_ok=%v\n", queryResults.GetIDGroups()[0][0], queryResults.GetDocumentsGroups()[0][0], math.Abs(float64(distance)-0.7525849) < 1e-3)
+	ids := queryResults.GetIDGroups()[0]
+	docs := queryResults.GetDocumentsGroups()[0]
+	distances := queryResults.GetDistancesGroups()[0]
+	distanceOk := math.Abs(float64(distances[0])-0.7525849) < 1e-3
+	fmt.Printf("Result of query: %v %v distance_ok=%v\n", ids[0], docs[0], distanceOk)

Comment thread modules/chroma/examples_test.go
@tazarov tazarov requested a review from mdelapenya February 6, 2026 10:33
Copy link
Copy Markdown
Member

@mdelapenya mdelapenya left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@mdelapenya mdelapenya added the enhancement New feature or request label Feb 6, 2026
@mdelapenya mdelapenya self-assigned this Feb 6, 2026
@mdelapenya mdelapenya merged commit b3c2ab1 into testcontainers:main Feb 6, 2026
16 of 17 checks passed
@tazarov tazarov deleted the feat/chroma-go-v0.3.2-update branch March 2, 2026 16:19
mdelapenya added a commit that referenced this pull request Mar 9, 2026
…m-v2

* upstream/main: (269 commits)
  chore(deps): bump actions/checkout from 6.0.1 to 6.0.2 (#3560)
  chore(deps): bump go.opentelemetry.io/otel/sdk to v1.41.0 (#3589)
  feat: add TiDB module (#3575)
  feat: add Forgejo module (#3556)
  feat: improve container conflict detection (#3574)
  chore(deps): bump go to 1.25 everywhere (#3572)
  chore(pulsar): bump base image to 4.x, replacing the wait for log strategy with wait for listening port (deterministic) (#3573)
  chore(deps): bump github.com/sigstore/sigstore in /modules/compose (#3571)
  chore(compose): update to compose-v5 (#3568)
  chore(deps): bump github.com/modelcontextprotocol/go-sdk (#3557)
  chore(deps): bump mkdocs-codeinclude-plugin from 0.2.1 to 0.3.1 (#3561)
  chore: update usage metrics (2026-03-02) (#3565)
  chore(deps): bump mkdocs-include-markdown-plugin from 7.2.0 to 7.2.1 (#3562)
  chore(deps): bump go.opentelemetry.io/otel/sdk in /modules/grafana-lgtm (#3563)
  chore(deps): bump go.opentelemetry.io/otel/sdk in /modules/toxiproxy (#3564)
  feat(azure): add lowkey vault container (#3542)
  feat(chroma): update to chroma 1.x (#3552)
  chore(deps): bump mkdocs-include-markdown-plugin from 7.2.0 to 7.2.1 (#3547)
  chore(deps): bump tj-actions/changed-files from 47.0.0 to 47.0.1 (#3546)
  chore(deps): bump actions/upload-artifact from 4.6.2 to 6.0.0 (#3545)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants