Skip to content

[build] Add a local development kit for contributors - #3851

Merged
wuchong merged 34 commits into
apache:mainfrom
Gezi-lzq:build/devkit
Nov 6, 2026
Merged

wuchong merged 34 commits into
apache:mainfrom
Gezi-lzq:build/devkit

Conversation

@Gezi-lzq

@Gezi-lzq Gezi-lzq commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Closes #3850.

Add a contributor-oriented DevKit for building the current checkout and running repeatable local end-to-end scenarios without building a custom Fluss image.

  • No generative AI tools used
  • Yes, OpenAI Codex was used to assist design, implementation, testing, and review

Brief change log

  • Add a profile-driven Docker Compose and just environment for Core, Gateway, Paimon, Iceberg, and Lance scenarios with one or three TabletServers
  • Mount locally built Fluss, Flink, Lake, and Gateway artifacts into runtime containers
  • Separate artifact preparation from startup: just build <profile> compiles and downloads dependencies, while just up <profile> only stages, starts, and waits for prepared artifacts
  • Provide stable lifecycle and validation commands for SQL execution, service status, logs, container execution, Tiering Job validation, shutdown, and cleanup
  • Keep runtime selection, Compose overlays, dependency staging, readiness checks, and the active profile behind the profile interface; reject unknown, duplicate, or incomplete runtime target sets
  • Add Core and Lake SQL examples plus automated Gateway and Paimon smoke coverage
  • Keep Paimon and Iceberg profile dependencies aligned with the versions managed by the root POM

Tests

  • RustFS client update: rustfs/rc:v0.1.36; actual DevKit Compose initialization and repeated bucket creation passed against rustfs/rustfs:1.0.0-alpha.83; git diff --check and ./mvnw -N spotless:check validate passed
  • ./mvnw validate
  • just --fmt --check
  • actionlint .github/workflows/devkit-smoke.yaml
  • Rendered every Core, Gateway, Paimon, Iceberg, and Lance Compose configuration with both single-node and three-TabletServer topologies
  • Started a three-TabletServer Core cluster and waited for all services to become healthy
  • Exercised the Gateway profile through the REST databases endpoint
  • Exercised the Paimon profile from clean volumes, including two cold starts, table setup, a running format-specific Tiering Job, Union Read results from both Fluss and Paimon, and Lake-only Read results for Alice and Bob
  • Verified tiering-status success and its stopped-cluster/no-active-profile failure paths
  • Added a Smoke workflow that checks managed dependency versions, exercises Gateway REST, and runs the Paimon SQL examples

Full mvn verify was not run locally; this change is covered by Maven validation and the DevKit end-to-end checks above.

API and Format

No public API or storage format changes.

Documentation

Add devkit/README.md defining the profile and runtime.targets contracts and covering prerequisites, build/start responsibilities, example workflows, lifecycle operations, and endpoints.

@Gezi-lzq
Gezi-lzq force-pushed the build/devkit branch 3 times, most recently from de731d7 to ca4f94d Compare August 5, 2026 05:08
@Gezi-lzq
Gezi-lzq marked this pull request as ready for review August 5, 2026 10:24
@Gezi-lzq
Gezi-lzq marked this pull request as draft August 5, 2026 16:03
@Gezi-lzq
Gezi-lzq marked this pull request as ready for review August 5, 2026 16:03
@Gezi-lzq

Gezi-lzq commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Hi @luoyuxia and @fresh-borzoni, I opened this PR based on my experience getting started with Fluss. I’d appreciate your thoughts on the overall direction and scope when you have time. Thanks!

@Gezi-lzq

Copy link
Copy Markdown
Contributor Author

I recommend trying the DevKit introduced by this PR locally. Compared with starting tests from IntelliJ or building Docker images and assembling a custom Docker Compose setup, it provides a more convenient workflow and makes it easier for both developers and coding agents to launch Fluss for end-to-end testing and troubleshooting.

I have frequently used a similar approach in the AutoMQ DevKit, and found it helpful for local development. I believe it could provide a similar improvement to the Fluss development experience.

@Gezi-lzq

Copy link
Copy Markdown
Contributor Author

Hi @wuchong @luoyuxia @swuferhong, this PR adds a local DevKit for Fluss contributors. It is a development tooling contribution rather than a user-facing feature, so I’d appreciate your thoughts on whether it fits the project and any feedback when you have time. If it is not a good fit for the repository or the current scope, please feel free to let me know. Thanks!

@fresh-borzoni fresh-borzoni left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Gezi-lzq Thank you for the PR and sorry for the long turnaround.
I think it can be useful for the project overall.

First, nothing tests the distribution as shipped. ITCases build a Configuration in Java and start servers in-process, so server.yaml parsing, the bin/ scripts and the plugins/<format>/ classloaders never run. Only the server loads lake plugins through a real PluginManager, but LakeTieringJobBuilder, LakeSourceUtils and every test pass null and use the flat classpath.

Second, nothing tests against a remote filesystem. That's how HoodieFlinkEngineContext.DEFAULT slipped through as tiering ITCases write to a local temp dir where an empty Hadoop conf works fine.
Your S3-backed profile is what exposed it.

Right now the only place Fluss runs for real is someone's laptop, set up
by hand, which is why wrong config can sit in our docs for months. If this lands, the quickstart pages can point at it instead of carrying their own compose blocks, so what we document is what we run. After that, a new lake format or filesystem plugin ships with a profile and its packaging gets checked when it's added. And it gives the cross-process things: TLS listeners, the k8s health contract - somewhere to be run properly, which a single-JVM ITCase can't do.

+1 on the CI smoke tests you mentioned, shall we do them in this PR rather than later, otherwise breakage stays silent until someone tries to run it?
Also devkit/** isn't in our paths-ignore, so a compose-only edit runs the whole Java matrix today.

Should this live under docker/? docker/quickstart-flink/ already has init_paimon.sh /init_iceberg.sh and a sample SQL file.

I'm thinking we keep this PR to the devkit and split out the HudiWriteTableInfo change to fix this issue. WDYT?

Comment thread devkit/compose/tiering.yml Resolved
Comment thread devkit/profiles/hudi/server.yaml Resolved
Comment thread devkit/tests/paimon-create-table.sql Resolved
Comment thread devkit/docker-compose.yml Resolved
Comment thread devkit/docker-compose.yml Resolved
Comment thread devkit/profiles/hudi/server.urls Resolved
@Gezi-lzq

Copy link
Copy Markdown
Contributor Author

Sorry for the delayed update—I only got a chance to update the PR today. Thanks for the detailed feedback and support.
I’ve added the DevKit Smoke workflow and updated the CI path filters so DevKit-only changes do not trigger the full Java matrix.
I prefer keeping it under devkit/ because it is intended for day-to-day contributor development and validation, as well as documentation reuse. It also covers process-level checks such as Docker init, JDWP, and Prometheus endpoints. I’ve updated AGENTS.md accordingly.
HudiWriteTableInfo will be handled in a follow-up PR. The Hudi DevKit profile and examples have been removed for now.
cc: @fresh-borzoni

@Gezi-lzq

Copy link
Copy Markdown
Contributor Author

Hi @beryllw, I noticed the recent work on the Gateway lakehouse quickstart. #3851 also includes a contributor-focused Gateway scenario that builds and runs Gateway from the current checkout against a real Fluss cluster, covering readiness, metadata access, REST writes, and configuration or integration changes.
From a Gateway development perspective, could you take a look and let me know whether this workflow would be useful and what it might still be missing for day-to-day development? Thanks!

@fresh-borzoni fresh-borzoni left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Gezi-lzq Thank you, good changes, run the devkit, LGTM overall, collected some comments and question, PTAL

Comment thread .github/workflows/devkit-smoke.yaml Resolved
Comment thread .github/workflows/devkit-smoke.yaml Resolved
Comment thread devkit/docker-compose.yml Resolved
Comment thread devkit/compose/tiering.yml Resolved
Comment thread devkit/justfile Resolved
Comment thread devkit/justfile Resolved
Comment thread AGENTS.md Resolved
Comment thread devkit/examples/core/streaming-scan.sql Resolved
Comment thread devkit/docker-compose.yml Resolved
@Gezi-lzq

Gezi-lzq commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

Hi @fresh-borzoni, apologies for the delayed follow-up, and thank you again for the detailed review. I’ve addressed the points you raised and pushed the changes to the PR. Please take another look when convenient.

@fresh-borzoni fresh-borzoni left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Gezi-lzq Thank you, lgtm overall, please rebase.

@wuchong @polyzos this adds a one-command local Fluss + Flink + lake setup built from your checkout, so you can test changes end to end without wiring it up by hand, with CI keeping it working. WDYT?

@wuchong wuchong left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you please rebase this branch onto the latest main instead of merging main into it? Keeping the history linear will make this PR easier to review and merge.

@wuchong wuchong left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for putting this together. I see real value in this PR. Beyond making local development and validation easier, what I value most is the foundation it provides for E2E testing suite in CI, an important gap in Fluss’s current test coverage.

Comment thread .github/workflows/ci.yaml Resolved
Comment thread .github/workflows/devkit-smoke.yaml Resolved
Comment thread .github/workflows/devkit-smoke.yaml Resolved
Comment thread devkit/profiles/core/server.yaml Resolved
Add a Docker Compose and just based development kit that runs locally built Fluss artifacts and supports core, Iceberg, Paimon, Lance, and Hudi profiles with manual tiering validation commands.

Run Fluss processes under Docker init, enable JDWP and Prometheus metrics, and propagate configured Hadoop settings to the Hudi write client so the S3A-backed Hudi profile retains its endpoint and credentials.
Stage profile-declared dependencies and Compose overlays for both lake and non-lake profiles. Keep Server JAR cleanup ownership explicit, align local runtime versions, and document the configuration rationale and validation boundaries.
Markdown files are excluded by the repository RAT configuration, consistent with the DevKit README.
Keep the PR focused on the implementation and concise usage documentation, and remove the README link to the deleted design note.
DevKit changes do not affect Java sources, so exclude them from the full Java CI workflow while retaining the separate license check.
Add core SQL examples and DevKit smoke coverage, tune snapshot and tiering polling intervals, and remove the temporary Hudi profile.
Keep lake examples under devkit/examples and remove the format-specific shortcut recipes so the workflow is explicit and easier to explore. Update the smoke workflow to execute the Paimon SQL chain directly.
Compile the Gateway in its pinned Rust environment, mount the local executable into a lightweight runtime container, and validate REST connectivity in the DevKit smoke workflow.
Replace the separate build recipes with one explicit core, tiering, or gateway target and keep startup recipes focused on starting prebuilt artifacts.
Declare runtime components per profile so build and startup dependencies stay aligned. Load Flink and Gateway overlays from runtime targets, mount the standard Gateway configuration, and document how contributors tailor complete local test scenarios.
Align managed Paimon dependencies with the root POM, strengthen Gateway and Paimon smoke coverage, and clarify the profile-driven build and runtime lifecycle.

Keep startup offline after an explicit build, validate readiness and the active Tiering Job, and remove the unrelated Hudi behavior change.
Run the DevKit smoke workflow only when files under devkit change.
Run the Paimon SQL examples directly without parsing or polling their result output.
Derive build steps from runtime targets and remove the duplicate build target files.

Use the active Compose profile for runtime checks, rely on Compose healthchecks for Flink readiness, and remove unused build command overrides.
Document profiles as complete local test scenarios and define runtime.targets as the single declaration for built-in runtime groups.\n\nValidate target names, duplicates, and dependencies before emitting targets or downloading profile dependencies.
Lead contributors from choosing a test scenario through validation, iteration, and diagnostics before introducing the profile contract as reference material.
Replace the unavailable minio/mc image with rustfs/rc:v0.1.36 and use rc for the shared lake profile bucket initialization.

AI-assisted with OpenAI Codex.
Keep profile build and runtime state explicit, preserve command arguments, verify downloaded artifacts, stream SQL output, and bind development ports to localhost.
Use supported scan modes, make lookup output observable, model Lance tiering with embedding events, and document each profile's user journey.
Exercise one minimal closed loop per profile, keep lifecycle recovery out of smoke coverage, and run the expensive workflow only for DevKit changes.
Use unittest selection for profile smoke checks and reuse just for setup and cleanup. Keep CI steps named by profile and assert observable results in each case.
Share the RustFS Compose overlay across all profiles and stage the filesystem plugin for Flink in common profile setup. This lets the core smoke scan read from its S3 remote data directory.
Check full Core rows, Gateway column metadata, and Paimon union output. Keep Lance data checks active when Python optimization is enabled.
@Gezi-lzq

Gezi-lzq commented Nov 5, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for putting this together. I see real value in this PR. Beyond making local development and validation easier, what I value most is the foundation it provides for E2E testing suite in CI, an important gap in Fluss’s current test coverage.

Thanks, I agree that this could be a useful foundation for E2E testing in CI. The current smoke tests already run a few small end-to-end flows against real services and check their results.

I haven’t yet worked out how to structure a broader E2E suite or systematically cover Fluss’s different features. I think these profiles and smoke cases are a good starting point, and we can build on them as the testing needs become clearer. I also expect DevKit to be useful in day-to-day development for starting Fluss, reproducing issues, and validating changes locally.

@wuchong wuchong left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM.

@wuchong
wuchong merged commit 0689a1b into apache:main Nov 6, 2026
7 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.

[Feature] Add a local development kit for contributors

3 participants