Skip to content

Conversation

@mkysel
Copy link
Collaborator

@mkysel mkysel commented May 19, 2025

Replace dynamic contract deployments with pre-baked Docker image to speed up anvil-based blockchain tests

Replaces the test environment setup across multiple test files by removing dynamic contract deployments and introducing a Docker-based approach using testcontainers-go. The changes center around the anvil.go file which now uses a pre-configured Docker image ghcr.io/xmtp/contracts:sha-cff29fc containing pre-deployed contracts. Key changes include:

  • Removes all contract deployment functions from contracts.go and introduces fixed contract addresses in config.go
  • Modifies StartAnvil function to use Docker containers instead of direct anvil process execution
  • Updates all test files to use predefined contract addresses from NewContractsOptions instead of deploying new contracts
  • Improves concurrent testing in anvil_test.go using Go's native parallel test functionality

📍Where to Start

Start with the StartAnvil function in anvil.go which contains the core changes for the Docker-based test environment setup.


Macroscope summarized 16070ed.

Summary by CodeRabbit

  • Refactor

    • Updated test setup to use predefined contract addresses instead of deploying new smart contracts during tests.
    • Migrated Anvil test node startup to use Docker containers for improved reliability and isolation.
  • Chores

    • Removed contract deployment utilities and related tests no longer required due to the new approach.
    • Added constants for default contract addresses in test configurations.
  • Tests

    • Refactored concurrent Anvil startup tests to use parallel subtests for improved clarity and maintainability.

@mkysel mkysel requested a review from a team as a code owner May 19, 2025 18:37
@graphite-app
Copy link

graphite-app bot commented May 19, 2025

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • Queue - adds this PR to the back of the merge queue
  • Hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 19, 2025

"""

Walkthrough

This change removes all test-time deployments of smart contracts from the codebase. Instead of deploying contracts dynamically in test helpers, fixed contract addresses are now provided via constants in the configuration. All deployment helper functions and their tests are deleted. The Anvil test node startup is refactored to use Docker containers for improved test isolation and reliability.

Changes

File(s) Change Summary
pkg/blockchain/blockchainPublisher_test.go
pkg/blockchain/migrator/migrator_test.go
pkg/blockchain/ratesAdmin_test.go
pkg/blockchain/registryAdmin_test.go
pkg/indexer/app_chain/contracts/group_message_storer_test.go
pkg/indexer/app_chain/contracts/identity_update_storer_test.go
pkg/indexer/e2e_test.go
Removed all test-time smart contract deployments from test helper functions. Tests now use preconfigured contract addresses from configuration, eliminating dynamic contract deployment during test setup.
pkg/testutils/contracts.go Deleted all contract deployment helper functions and related Ethereum contract deployment logic. Removed all imports and code related to contract deployment.
pkg/testutils/contracts_test.go Deleted the test file containing tests for contract deployment helper functions.
pkg/testutils/config.go Added four new constant addresses for smart contracts. Updated NewContractsOptions to set these constants in the returned configuration struct, providing fixed addresses for use in tests.
pkg/testutils/anvil/anvil.go Refactored Anvil test node startup to use Docker containers via testcontainers-go. Added new helper for streaming container logs. Removed logic for direct process execution and manual port assignment.
pkg/testutils/anvil/anvil_test.go Refactored concurrency test for Anvil startup to use Go subtests with t.Parallel() instead of manual goroutine and channel management.

Sequence Diagram(s)

sequenceDiagram
    participant Test
    participant Config
    participant Anvil (Docker)
    Note over Test: Test setup (before)
    Test->>Anvil (Docker): Start test node
    Test->>Test: Deploy contract(s) via helper
    Test->>Config: Set contract address in config
    Test->>Test: Run test logic

    Note over Test: Test setup (after)
    Test->>Anvil (Docker): Start test node
    Test->>Config: Use fixed contract address from config
    Test->>Test: Run test logic
Loading

Possibly related PRs

  • xmtp/xmtpd#630: Adds contract deployment calls back into tests and updates deployment functions, which is directly related as it modifies the same deployment-related code and test setup functions.
    """

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (1.64.8)

Error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2
Failed executing command with error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


Note

⚡️ Faster reviews with caching

CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.
Enjoy the performance boost—your workflow just got faster.

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@mkysel mkysel linked an issue May 19, 2025 that may be closed by this pull request
@macroscopeapp
Copy link

macroscopeapp bot commented May 19, 2025

Replace dynamic contract deployment with pre-baked Docker image in Anvil-based tests to improve test reliability

  • Replaces local Anvil process execution with Docker container-based approach using testcontainers-go in anvil.go
  • Removes dynamic contract deployment code from test utilities and replaces with predefined contract addresses in config.go
  • Updates all blockchain and indexer tests to use pre-deployed contract addresses instead of deploying new contracts for each test
  • Modifies concurrent testing approach in anvil_test.go to use Go's native parallel test functionality

📍Where to Start

Start with the StartAnvil function in anvil.go which contains the core changes for Docker container implementation and sets up the pre-baked test environment.


Macroscope summarized 8f1c80d.

Copy link
Contributor

@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

🧹 Nitpick comments (5)
pkg/testutils/config.go (2)

16-20: Address constants are fine, but flag static duplication

Hard-coding contract addresses is reasonable for deterministic tests; however, we now have three places with private keys / addresses (TEST_PRIVATE_KEY above, LOCAL_PRIVATE_KEY in contracts.go, and these four constants). Consider keeping all blockchain test constants in a single file (or an addresses_test.go) to avoid drift.

🧰 Tools
🪛 GitHub Check: Lint-Go

[failure] 16-16:
File is not properly formatted (gofumpt)


24-37: Run gofumpt – file is not formatted

gofumpt flagged this file. A quick pass will reorder the composite literal fields and trim the extra alignment whitespace. This prevents CI lint noise later.

gofumpt -w pkg/testutils/config.go
pkg/testutils/anvil/anvil_test.go (1)

5-5: Nit: keep imports gofumpt-sorted

fmt should appear after the standard-library context import when using gofumpt.

pkg/testutils/anvil/anvil.go (2)

75-94: Redundant AutoRemove may race with explicit Terminate
Setting HostConfig.AutoRemove = true causes Docker to delete the container as soon as it exits. When t.Cleanup later calls Terminate, the container may already be gone, making the call a no-op or returning a “No such container” error (currently ignored).

If deterministic cleanup is important, either:

  1. Remove AutoRemove and rely solely on Terminate, or
  2. Keep AutoRemove but drop the explicit Terminate, or
  3. Keep both but check and deliberately ignore errNotFound in the cleanup for clarity.

This avoids hard-to-trace test flakiness on slow or overloaded runners.


81-86: Consider wait.ForListeningPort instead of polling client
Testcontainers already offers wait.ForListeningPort("8545/tcp"), which would allow you to delete the custom waitForAnvil function and its busy-wait loop. This reduces code and potential connection-race issues.

Example:

-WaitingFor: wait.ForLog("Listening on"),
+WaitingFor: wait.ForListeningPort("8545/tcp"),

…then you can safely remove waitForAnvil and the extra dial logic.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a9cbe1 and 16070ed.

📒 Files selected for processing (12)
  • pkg/blockchain/blockchainPublisher_test.go (0 hunks)
  • pkg/blockchain/migrator/migrator_test.go (0 hunks)
  • pkg/blockchain/ratesAdmin_test.go (0 hunks)
  • pkg/blockchain/registryAdmin_test.go (0 hunks)
  • pkg/indexer/app_chain/contracts/group_message_storer_test.go (0 hunks)
  • pkg/indexer/app_chain/contracts/identity_update_storer_test.go (0 hunks)
  • pkg/indexer/e2e_test.go (0 hunks)
  • pkg/testutils/anvil/anvil.go (2 hunks)
  • pkg/testutils/anvil/anvil_test.go (2 hunks)
  • pkg/testutils/config.go (1 hunks)
  • pkg/testutils/contracts.go (1 hunks)
  • pkg/testutils/contracts_test.go (0 hunks)
💤 Files with no reviewable changes (8)
  • pkg/blockchain/blockchainPublisher_test.go
  • pkg/indexer/e2e_test.go
  • pkg/blockchain/migrator/migrator_test.go
  • pkg/indexer/app_chain/contracts/identity_update_storer_test.go
  • pkg/blockchain/ratesAdmin_test.go
  • pkg/blockchain/registryAdmin_test.go
  • pkg/indexer/app_chain/contracts/group_message_storer_test.go
  • pkg/testutils/contracts_test.go
🧰 Additional context used
🧬 Code Graph Analysis (2)
pkg/testutils/anvil/anvil_test.go (2)
pkg/testutils/anvil/anvil.go (1)
  • StartAnvil (69-103)
pkg/blockchain/client.go (1)
  • NewClient (17-19)
pkg/testutils/config.go (1)
pkg/config/options.go (3)
  • ContractsOptions (16-32)
  • AppChainOptions (34-40)
  • SettlementChainOptions (42-49)
🪛 GitHub Check: Lint-Go
pkg/testutils/config.go

[failure] 16-16:
File is not properly formatted (gofumpt)

pkg/testutils/anvil/anvil.go

[failure] 6-6:
File is not properly formatted (gofumpt)

🪛 GitHub Actions: Lint
pkg/testutils/anvil/anvil.go

[error] 6-6: File is not properly formatted (gofumpt)

🪛 Gitleaks (8.26.0)
pkg/testutils/contracts.go

16-16: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Push Docker Images to GitHub Packages (xmtpd-cli)
  • GitHub Check: Test (Node)
  • GitHub Check: Push Docker Images to GitHub Packages (xmtpd)
  • GitHub Check: Upgrade Tests
🔇 Additional comments (3)
pkg/testutils/contracts.go (1)

12-13: testing import is fine, but make it explicit in build tags

Nothing blocking here; just confirming the extra import is required for helper assertions below.

pkg/testutils/anvil/anvil_test.go (1)

27-41: Concurrency looks good – verify container limits

Spinning up 10 Anvil containers concurrently is useful for stress-testing but may overwhelm CI runners with low CPU/memory quotas. If jobs start to flake, consider reading ANVIL_PARALLELISM from the environment to cap the number of sub-tests run in parallel.

pkg/testutils/anvil/anvil.go (1)

70-71: t.Context() requires Go 1.22 – verify tool-chain compatibility
testing.T.Context() was introduced very recently (Go 1.22). If your CI/build image or downstream users are still on ≤ 1.21, the project will fail to compile. Consider:

-ctx := t.Context()
+ctx, cancel := context.WithCancel(context.Background())
+t.Cleanup(cancel)

or bump the minimum Go version in go.mod (and CI) to 1.22+.

Comment on lines +16 to +21
const (
RATE_REGISTRY_ADDRESS = "0xE71ac6dE80392495eB52FB1dCa321f5dB8f51BAE"
NODE_REGISTRY_ADDRESS = "0x8d69E9834f1e4b38443C638956F7D81CD04eBB2F"
GROUP_MESSAGE_BROADCAST_ADDRESS = "0xD5b7B43B0e31112fF99Bd5d5C4f6b828259bedDE"
IDENTITY_UPDATE_BROADCAST_ADDRESS = "0xe67104BC93003192ab78B797d120DBA6e9Ff4928"
)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

we will have to figure out a better way to fetch these. Same for hardcoding the version of the contracts image. I will give it some thought and can create a followup PR

Copy link
Contributor

@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: 0

♻️ Duplicate comments (1)
pkg/testutils/contracts.go (1)

16-18: Hardcoded private key remains a security concern

The LOCAL_PRIVATE_KEY constant is still hardcoded in the code, which triggers security scanning tools like gitleaks and could lead to accidental exposure or misuse. This issue was previously identified in a prior review.

As suggested in the previous review, consider loading this key from an environment variable with a fallback:

-const (
-	LOCAL_PRIVATE_KEY = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
-)
+// Anvil image pre-funded key. Override with XMTPD_TEST_PRIVATE_KEY if needed.
+var LOCAL_PRIVATE_KEY = func() string {
+	if v := os.Getenv("XMTPD_TEST_PRIVATE_KEY"); v != "" {
+		return v
+	}
+	return "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
+}()

Don't forget to add the missing import: import "os"

🧹 Nitpick comments (1)
pkg/testutils/contracts.go (1)

16-18: Add documentation about key usage with pre-baked image

Since this PR shifts testing to use a pre-baked Docker image instead of dynamic contract deployments, it would be helpful to document that this private key corresponds to a pre-funded account in the Docker image.

 const (
+	// Account pre-funded in the ghcr.io/xmtp/contracts:sha-cff29fc Docker image
+	// Used for testing with the pre-baked Anvil blockchain
 	LOCAL_PRIVATE_KEY = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
 )
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16070ed and 8f1c80d.

📒 Files selected for processing (3)
  • pkg/testutils/anvil/anvil.go (2 hunks)
  • pkg/testutils/config.go (1 hunks)
  • pkg/testutils/contracts.go (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • pkg/testutils/config.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/testutils/anvil/anvil.go
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Upgrade Tests
  • GitHub Check: Test (Node)

@mkysel mkysel requested a review from neekolas May 19, 2025 18:54
@mkysel mkysel merged commit f51d475 into main May 19, 2025
9 checks passed
@mkysel mkysel deleted the mkysel/use-docker-for-anvil branch May 19, 2025 19:47
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.

0.4.0 contracts make it impossible to deploy contracts in tests

3 participants