Skip to content

TestContainers labels#2

Merged
dragosv merged 1 commit intomainfrom
testcontainers-labels
Mar 7, 2026
Merged

TestContainers labels#2
dragosv merged 1 commit intomainfrom
testcontainers-labels

Conversation

@dragosv
Copy link
Copy Markdown
Owner

@dragosv dragosv commented Mar 7, 2026

Implement full Testcontainers label specification

Summary

Implements the standard Testcontainers label specification across all Docker resources (containers and networks), aligning with the conventions established by the Java and Ruby reference implementations.

Problem

Only two labels were applied to containers (org.testcontainers.lang and org.testcontainers.version), and none were applied to networks. The official Testcontainers specification requires four labels on every resource, including the org.testcontainers marker and a per-process sessionId used by the Ryuk resource reaper for cleanup.

Changes

src/testcontainers/docker_client.cr

  • Added label key constants: TESTCONTAINERS_LABEL, TESTCONTAINERS_SESSION_ID_LABEL, TESTCONTAINERS_LANG_LABEL, TESTCONTAINERS_VERSION_LABEL
  • Added SESSION_ID — a per-process UUID shared across all resources
  • Added DockerClient.default_labels returning the full canonical label set

src/testcontainers/docker_container.cr

  • default_labels now delegates to DockerClient.default_labels

src/testcontainers/network.cr

  • Added labels getter initialized from DockerClient.default_labels
  • Passes labels to Docr::Types::NetworkConfig on network creation

spec/docker_container_spec.cr

  • Expanded label assertions to cover all four labels (org.testcontainers, sessionId, lang, version)
  • Added test verifying session id consistency across multiple containers

spec/network_spec.cr

  • Added label assertions matching the container label spec

spec/integration_spec.cr

  • Added integration test that creates a real container and network, then inspects Docker metadata to verify all labels are present with the correct session id

Labels applied to resources

Label Value Purpose
org.testcontainers "true" Marker for Ryuk cleanup / resource identification
org.testcontainers.sessionId UUID (per process) Groups resources by test session for targeted cleanup
org.testcontainers.lang "crystal" Identifies the client language
org.testcontainers.version Testcontainers::VERSION Identifies the library version

Testing

  • Unit tests: 68 examples, 0 failures
  • Integration test (requires Docker): validates labels on actual container and network inspect responses

Summary by Sourcery

Add standardized Testcontainers metadata labels to Docker containers and networks and ensure they are applied consistently across resources within a session.

New Features:

  • Apply a common set of Testcontainers metadata labels to all managed Docker containers and networks, including a shared session identifier, language, and library version.

Tests:

  • Add unit tests for default labels on containers and networks and for consistent session IDs across containers.
  • Add integration test verifying Testcontainers labels are present on created containers and networks.

Summary by CodeRabbit

  • New Features

    • Networks now include default Testcontainers labels for session tracking, language, and version.
    • Networks expose a labels property so labels can be inspected programmatically.
  • Tests

    • Added tests verifying default labels are applied to containers and networks.
    • Added tests ensuring session ID consistency across container instances.
    • Added integration tests confirming labels are set on both containers and their networks.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Mar 7, 2026

Reviewer's Guide

Adds standardized Testcontainers marker labels (including a shared session ID) to containers and networks, centralizes label definitions in DockerClient, and extends tests to verify label application and consistency across resources.

Sequence diagram for Docker network creation with default labels

sequenceDiagram
  participant Network
  participant DockerClient
  participant DocrAPI
  participant DockerEngine

  Network->>DockerClient: default_labels()
  DockerClient-->>Network: Hash(String, String)

  Network->>DockerClient: api()
  DockerClient-->>Network: DocrAPI

  Network->>DocrAPI: networks.create(name, driver, check_duplicate, labels)
  DocrAPI->>DockerEngine: HTTP POST /networks/create with labels
  DockerEngine-->>DocrAPI: network_id
  DocrAPI-->>Network: network_id
  Network->>Network: store network_id
Loading

Class diagram for Testcontainers Docker label handling

classDiagram
  class Testcontainers {
  }

  class DockerClient {
    <<module>>
    +DocrAPI api
    +String TESTCONTAINERS_LABEL
    +String TESTCONTAINERS_SESSION_ID_LABEL
    +String TESTCONTAINERS_LANG_LABEL
    +String TESTCONTAINERS_VERSION_LABEL
    +String SESSION_ID
    +get : DocrAPI
    +reset : Nil
    +default_labels() Hash~String, String~
    +host() String
  }

  class DockerContainer {
    +start() Nil
    +stop() Nil
    -default_labels() Hash~String, String~
  }

  class Network {
    +String name
    +String driver
    +String network_id
    +Hash~String, String~ labels
    +create() Nil
  }

  Testcontainers <|-- DockerClient
  Testcontainers <|-- DockerContainer
  Testcontainers <|-- Network

  DockerContainer ..> DockerClient : uses_default_labels
  Network ..> DockerClient : uses_default_labels
Loading

File-Level Changes

Change Details Files
Centralize Testcontainers label definitions and defaults in DockerClient, including a shared session ID.
  • Introduce constants for Testcontainers label keys (base label, session ID, language, version).
  • Generate a process-wide SESSION_ID using UUID.random and expose it on DockerClient.
  • Add DockerClient.default_labels helper returning the standard Testcontainers label set (marker, session ID, lang, version).
src/testcontainers/docker_client.cr
Apply default Testcontainers labels to Docker containers and networks using the centralized helper.
  • Change DockerContainer.default_labels to delegate to DockerClient.default_labels so containers inherit the full label set including marker and session ID.
  • Add a labels field to Network, initialized from DockerClient.default_labels in the constructor.
  • Include network labels in the Docker network create request payload so labels are applied on network creation.
src/testcontainers/docker_container.cr
src/testcontainers/network.cr
Extend tests to verify default labels and session ID behavior on containers and networks, and label propagation to created resources.
  • Add expectations in DockerContainer specs to assert presence of Testcontainers marker and session ID labels, and that multiple containers share the same session ID.
  • Add Network specs to assert that default labels are set on network instances.
  • Add integration spec ensuring both container and network created via Testcontainers have the expected Testcontainers labels and matching session ID and version.
spec/docker_container_spec.cr
spec/network_spec.cr
spec/integration_spec.cr

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 7, 2026

📝 Walkthrough

Walkthrough

Adds centralized default labels (including a session ID, language, version, and marker) in DockerClient and applies them to containers and networks; tests added to verify labels on DockerContainer and Network, and an integration test checks labels are present on both container and network.

Changes

Cohort / File(s) Summary
Tests
spec/docker_container_spec.cr, spec/network_spec.cr, spec/integration_spec.cr
Added tests asserting default labels (org.testcontainers, org.testcontainers.sessionId, org.testcontainers.lang, org.testcontainers.version) exist and match DockerClient::SESSION_ID / Testcontainers::VERSION on containers and networks.
DockerClient core
src/testcontainers/docker_client.cr
Added UUID dependency, new label constants and SESSION_ID, and def self.default_labels : Hash(String, String) returning standardized label map.
Container & Network integration
src/testcontainers/docker_container.cr, src/testcontainers/network.cr
DockerContainer delegated default label construction to DockerClient.default_labels; Network gained a public labels getter, initializes @labels = DockerClient.default_labels, and includes labels when creating the Docker network.

Sequence Diagram(s)

mermaid
sequenceDiagram
autonumber
participant Test as Test / Caller
participant DockerClient as DockerClient
participant Network as Network
participant Container as DockerContainer
Test->>DockerClient: request default_labels()
DockerClient-->>Test: returns label map (org.testcontainers, sessionId, lang, version)
Test->>Network: initialize with labels (from DockerClient)
Network->>Docker Engine: create network with labels
Test->>Container: initialize/start with labels (from DockerClient)
Container->>Docker Engine: create/start container with labels

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I scoped a UUID, stitched labels with care,

session IDs hopping through network and lair,
Containers and nets wear the same little sign,
Crystal-raised badges, aligned and divine.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'TestContainers labels' is vague and generic, lacking specificity about what was done with the labels. Provide a more descriptive title such as 'Add standardized Testcontainers labels to containers and networks' or 'Implement Testcontainers metadata labels for Docker resources'.
✅ Passed checks (2 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The pull request description comprehensively covers the changes, includes detailed explanations of the problem and solution, provides a clear label specification table, and references testing performed.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch testcontainers-labels

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

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • In integration_spec.cr, network_labels = network.info.labels is used without a nil check (unlike container_labels), so consider asserting non-nil or using not_nil! consistently before indexing into network_labels to avoid potential crashes if labels are ever missing.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `integration_spec.cr`, `network_labels = network.info.labels` is used without a nil check (unlike `container_labels`), so consider asserting non-nil or using `not_nil!` consistently before indexing into `network_labels` to avoid potential crashes if labels are ever missing.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/testcontainers/docker_client.cr (1)

1-41: ⚠️ Potential issue | 🟡 Minor

Fix Crystal formatting to resolve CI failure.

The pipeline indicates that crystal tool format produces changes for this file. The hash literal alignment in the default_labels method (lines 36-39) likely uses inconsistent whitespace padding that the formatter will normalize.

Run crystal tool format ./src/testcontainers/docker_client.cr to fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/testcontainers/docker_client.cr` around lines 1 - 41, The hash literal in
DockerClient.default_labels has inconsistent whitespace/padding that fails
crystal tool format; run `crystal tool format` on the file (or reformat the hash
so keys and values are aligned per Crystal style) to normalize spacing around
the hash braces and between keys/values for TESTCONTAINERS_LABEL,
TESTCONTAINERS_SESSION_ID_LABEL, TESTCONTAINERS_LANG_LABEL and
TESTCONTAINERS_VERSION_LABEL (or simply run `crystal tool format
./src/testcontainers/docker_client.cr`) and commit the formatted change.
🧹 Nitpick comments (1)
src/testcontainers/network.cr (1)

22-22: Consider adding a doc comment for the labels getter.

As per coding guidelines, all public APIs in src/**/*.cr should have # doc comments. A brief description would help users understand this property.

📝 Suggested doc comment
     getter network_id : String?
+    # Returns the labels applied to this network.
     getter labels : Hash(String, String)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/testcontainers/network.cr` at line 22, Add a Crystal doc comment for the
public getter `labels` in src/testcontainers/network.cr: describe what the
`labels : Hash(String, String)` property represents (e.g., network
metadata/labels used for identification or Docker labels), any important
behaviour or constraints, and an example or note if relevant; place the comment
immediately above the `getter labels` declaration so it appears in generated
docs for the `labels` getter.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/testcontainers/docker_client.cr`:
- Around line 1-41: The hash literal in DockerClient.default_labels has
inconsistent whitespace/padding that fails crystal tool format; run `crystal
tool format` on the file (or reformat the hash so keys and values are aligned
per Crystal style) to normalize spacing around the hash braces and between
keys/values for TESTCONTAINERS_LABEL, TESTCONTAINERS_SESSION_ID_LABEL,
TESTCONTAINERS_LANG_LABEL and TESTCONTAINERS_VERSION_LABEL (or simply run
`crystal tool format ./src/testcontainers/docker_client.cr`) and commit the
formatted change.

---

Nitpick comments:
In `@src/testcontainers/network.cr`:
- Line 22: Add a Crystal doc comment for the public getter `labels` in
src/testcontainers/network.cr: describe what the `labels : Hash(String, String)`
property represents (e.g., network metadata/labels used for identification or
Docker labels), any important behaviour or constraints, and an example or note
if relevant; place the comment immediately above the `getter labels` declaration
so it appears in generated docs for the `labels` getter.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 21f65570-7b97-4cb0-9a8f-32472d38c6f1

📥 Commits

Reviewing files that changed from the base of the PR and between b5c5648 and eb8e0d2.

📒 Files selected for processing (6)
  • spec/docker_container_spec.cr
  • spec/integration_spec.cr
  • spec/network_spec.cr
  • src/testcontainers/docker_client.cr
  • src/testcontainers/docker_container.cr
  • src/testcontainers/network.cr

@dragosv dragosv force-pushed the testcontainers-labels branch from eb8e0d2 to 1e35dd1 Compare March 7, 2026 06:11
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 59.35%. Comparing base (c63c3d6) to head (1e35dd1).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main       #2      +/-   ##
==========================================
+ Coverage   58.50%   59.35%   +0.84%     
==========================================
  Files          14       14              
  Lines         335      342       +7     
==========================================
+ Hits          196      203       +7     
  Misses        139      139              
Flag Coverage Δ
unittests 59.35% <100.00%> (+0.84%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

🧹 Nitpick comments (1)
src/testcontainers/network.cr (1)

22-22: Consider adding a doc comment for the labels getter.

Per coding guidelines, public APIs should have # doc comments. A brief description of the labels' purpose and structure would help users understand this property.

+    # Returns the metadata labels applied to this network.
     getter labels : Hash(String, String)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/testcontainers/network.cr` at line 22, Add a RubyCrystal doc comment
above the getter `labels : Hash(String, String)` (use a `#` comment immediately
above the declaration) that briefly explains this property holds the network's
label metadata as string key/value pairs, describes the intended use (e.g.,
container/network metadata or Docker labels), and notes the expected format
(Hash(String, String)). Reference the `labels` getter when adding the comment so
users can see purpose and structure in the public API.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/testcontainers/network.cr`:
- Line 22: Add a RubyCrystal doc comment above the getter `labels : Hash(String,
String)` (use a `#` comment immediately above the declaration) that briefly
explains this property holds the network's label metadata as string key/value
pairs, describes the intended use (e.g., container/network metadata or Docker
labels), and notes the expected format (Hash(String, String)). Reference the
`labels` getter when adding the comment so users can see purpose and structure
in the public API.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 247c84a4-2c32-4b1f-aca7-e6a0d3043fbd

📥 Commits

Reviewing files that changed from the base of the PR and between eb8e0d2 and 1e35dd1.

📒 Files selected for processing (6)
  • spec/docker_container_spec.cr
  • spec/integration_spec.cr
  • spec/network_spec.cr
  • src/testcontainers/docker_client.cr
  • src/testcontainers/docker_container.cr
  • src/testcontainers/network.cr
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/testcontainers/docker_client.cr
  • src/testcontainers/docker_container.cr
  • spec/integration_spec.cr
  • spec/network_spec.cr

@dragosv dragosv merged commit 528f4b8 into main Mar 7, 2026
9 checks passed
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.

1 participant