Skip to content

Conversation

@ilopezluna
Copy link
Contributor

@ilopezluna ilopezluna commented Oct 30, 2025

This pull request introduces integration testing support for the CLI, enabling end-to-end validation of model registry and runner interactions using Docker containers.

model-cli (what its being tested) <----> DMR (Testcontainer) <----> OCI Registry (Testcontainer)
The registry is set as the default one in here.

We can easily add more tests, for other commands like tag, configure, etc, but it can be done in a followup PR.
I added a separated workflow because it needs to build the DMR image (the current latest does not include the env variable to customize default registry yet), once we publish a new latest we can move the workflow to the normal CI.

The PR also contains a fix for the inspect command.

@mdelapenya could you please take a look? Let us know any recommendation you might have 🙏

Copy link
Contributor

@doringeman doringeman left a comment

Choose a reason for hiding this comment

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

LGTM! Why isn't the integration-tests rule in the root Makefile?

@ilopezluna ilopezluna force-pushed the add-testcontainers branch 2 times, most recently from 3491233 to 2c7b497 Compare October 31, 2025 14:45
@ilopezluna ilopezluna changed the title feat(tests): add integration tests using Testcontainers [WIP] add integration tests using Testcontainers Nov 3, 2025
@@ -0,0 +1,37 @@
name: Integration Tests
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm adding this additional workflow because I have to build the DMR image before running tests. This temporary, integration test should be run in the normal CI workflow

@ilopezluna ilopezluna changed the title [WIP] add integration tests using Testcontainers Add integration tests using Testcontainers Nov 3, 2025
tag string // e.g., "latest"
registry string // e.g., "registry.local:5000"
modelID string // Full ID: sha256:...
digest string // sha256:...
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note: modelID and digest are exactly the same (the digest of the manifest) I just added 2 fields to make it more readable

@ilopezluna
Copy link
Contributor Author

ilopezluna commented Nov 3, 2025

LGTM! Why isn't the integration-tests rule in the root Makefile?

I keep it in a separated workflow for now because we need to build DMR image with current version of DMR, otherwise we cannot define the default registry

@ilopezluna ilopezluna marked this pull request as ready for review November 3, 2025 21:05
@ilopezluna ilopezluna requested a review from doringeman November 3, 2025 21:05
Copy link
Contributor

@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 there - I've reviewed your changes - here's some feedback:

  • integration_test.go is very large—consider breaking it into smaller files or extracting common setup/teardown logic into helper functions to improve readability and maintainability.
  • The go.mod diff includes a lot of indirect module updates; please run go mod tidy to remove unused dependencies and keep the module file clean.
  • Instead of calling testcontainers.CleanupContainer/Network directly, register cleanup with t.Cleanup so resources are always cleaned up even if setup fails early.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- integration_test.go is very large—consider breaking it into smaller files or extracting common setup/teardown logic into helper functions to improve readability and maintainability.
- The go.mod diff includes a lot of indirect module updates; please run `go mod tidy` to remove unused dependencies and keep the module file clean.
- Instead of calling testcontainers.CleanupContainer/Network directly, register cleanup with t.Cleanup so resources are always cleaned up even if setup fails early.

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.

@ilopezluna ilopezluna requested review from a team and mdelapenya November 4, 2025 08:50

- name: Run integration tests
working-directory: cmd/cli/commands
run: go test -v -tags=integration -timeout=5m -run TestIntegration_PullModel
Copy link
Contributor

Choose a reason for hiding this comment

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

Why only PullModel?

Comment on lines +9 to +26
runs-on: ubuntu-latest
timeout-minutes: 10

steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8

- name: Set up Go
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00
with:
go-version: 1.24.2
cache: true

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435

- name: Run integration tests
run: make integration-tests

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 7 days ago

To fix the problem, explicitly define a permissions block with the least privilege needed. Since this workflow job (integration-test) only checks out code and runs tests but does not perform any write operations, the minimal permission needed is contents: read. The best approach is to add:

permissions:
  contents: read

This block can be added at the workflow root (applies to all jobs), or more specifically, to the integration-test job (since there’s only one job here, either location is functionally the same). Place the block above or within the relevant job definition.

To implement this, add permissions: contents: read just below runs-on: ubuntu-latest and above timeout-minutes: 10 (line 9 in the snippet). No other changes or dependency modifications are necessary.


Suggested changeset 1
.github/workflows/integration-test.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml
--- a/.github/workflows/integration-test.yml
+++ b/.github/workflows/integration-test.yml
@@ -7,6 +7,8 @@
 jobs:
   integration-test:
     runs-on: ubuntu-latest
+    permissions:
+      contents: read
     timeout-minutes: 10
 
     steps:
EOF
@@ -7,6 +7,8 @@
jobs:
integration-test:
runs-on: ubuntu-latest
permissions:
contents: read
timeout-minutes: 10

steps:
Copilot is powered by AI and may make mistakes. Always verify output.
@@ -0,0 +1,464 @@
//go:build integration
Copy link
Member

Choose a reason for hiding this comment

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

suggestion: I'd avoid using the build tag unless necessary. Why? Because then you'll be running tests twice (adding the flag in the make file will run all AND will include files with this tag), so you can end up adding exclusions and complex boolean logic for this. My recommendation is to run them altogether, and treat in-process integration tests as unit tests, as they are blazing fast thanks to containers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a good point, thank you!

@ericcurtin
Copy link
Contributor

Minor nit, logs report error when we have a valid fallback:

cmd/cli/model-cli inspect smollm2:latest
INFO[0001] Getting model by reference: smollm2:latest    component=model-manager
ERRO[0001] Failed to get model: model not found reference: smollm2:latest  component=model-manager
INFO[0001] Getting model by reference: ai/smollm2:latest  component=model-manager
{
    "id": "sha256:354bf30d0aa3af413d2aa5ae4f23c66d78980072d1e07a5b0d776e9606a2f0b9",
    "tags": [
        "index.docker.io/ai/smollm2:latest",
        "my-smollm2:latest"
    ],
    "created": 1742816981,
    "config": {
        "format": "gguf",
        "quantization": "IQ2_XXS/Q4_K_M",
        "parameters": "361.82 M",
        "architecture": "llama",
        "size": "256.35 MiB"
    }
}
+ MODEL_RUNNER_HOST=http://localhost:13434
+ cmd/cli/model-cli inspect my-smollm2

@ericcurtin ericcurtin merged commit 6f0be5b into main Nov 4, 2025
10 checks passed
@ericcurtin ericcurtin deleted the add-testcontainers branch November 4, 2025 15:46
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.

5 participants