From 43558b590c0aeffe41da8bf015cc4c96979bc8e2 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Tue, 7 Apr 2026 14:40:37 +0900 Subject: [PATCH 1/4] Migrate from just to poe Signed-off-by: Anuraag Agrawal --- .github/workflows/ci.yaml | 18 ++---- .github/workflows/docs.yaml | 2 +- CONTRIBUTING.md | 9 ++- DEVELOPMENT.md | 21 +++--- README.md | 3 +- RELEASE.md | 4 +- connect-python.code-workspace | 1 - justfile | 73 --------------------- poe_tasks.toml | 116 ++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- uv.lock | 44 ++++++++----- 11 files changed, 169 insertions(+), 124 deletions(-) delete mode 100644 justfile create mode 100644 poe_tasks.toml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3271298..7165f56 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -67,37 +67,33 @@ jobs: go-version-file: protoc-gen-connect-python/go.mod cache-dependency-path: "**/go.mod" - - run: uv sync --all-packages + - run: uv sync --frozen - name: run lints if: startsWith(matrix.os, 'ubuntu-') - run: | - uv run ruff format --check . - uv run ruff check . - uv run pyright + run: uv run poe lint - name: run python tests - run: uv run pytest ${{ matrix.coverage == 'cov' && '--cov=connectrpc --cov-report=xml' || '' }} + run: uv run poe test ${{ matrix.coverage == 'cov' && '--cov=connectrpc --cov-report=xml' || '' }} - name: run conformance tests # TODO: Debug stdin/stdout issues on Windows if: ${{ !startsWith(matrix.os, 'windows-') }} - run: uv run pytest ${{ matrix.coverage == 'cov' && '--cov=connectrpc --cov-report=xml' || '' }} - working-directory: conformance + run: uv run poe test-conformance ${{ matrix.coverage == 'cov' && '--cov=connectrpc --cov-report=xml' || '' }} - name: run OTel tests - run: uv run pytest ${{ matrix.coverage == 'cov' && '--cov=connectrpc --cov-report=xml' || '' }} + run: uv run poe test-otel ${{ matrix.coverage == 'cov' && '--cov=connectrpc_otel --cov-report=xml' || '' }} working-directory: connectrpc-otel - name: run Go tests run: go test ./... working-directory: protoc-gen-connect-python - - name: check running `just generate` does not create a diff + - name: check running generate does not create a diff # NOTE: running on macOS as our sed command only works there # We expect uv.lock to change when matrix.resolution == "lowest-direct", so we don't check it there. if: ${{ startsWith(matrix.os, 'macos-') && matrix.resolution == 'highest' }} - run: uv run just checkgenerate + run: uv run poe checkgenerate env: BUF_TOKEN: ${{ secrets.BUF_TOKEN }} diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index c481e5f..e6dd332 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -33,7 +33,7 @@ jobs: - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 - - run: uv run --group docs --no-dev zensical build --clean + - run: uv run poe docs-build - uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0 if: github.event_name != 'pull_request' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9975393..2d070b2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,7 +24,6 @@ $ git commit -s -m "your commit message" - Python 3.10 or later - [uv](https://docs.astral.sh/uv/) for dependency management -- [just](https://just.systems/) for running tasks ### Installation @@ -38,13 +37,13 @@ $ git commit -s -m "your commit message" 2. Verify everything is working: ```console - $ uv run just check + $ uv run poe check ``` ## Development Workflow -We use `just` as our task runner. -Run `uv run just --list` to see all available commands. +We use `poe` as our task runner. +Run `uv run poe` to see all available commands. ## Submitting a Pull Request @@ -57,7 +56,7 @@ Run `uv run just --list` to see all available commands. 2. Make your changes and ensure all checks pass: ```console - $ uv run just check + $ uv run poe check ``` 3. Commit with a sign-off and a clear message, then push to your fork and open a pull diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 9864b26..ff92327 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -24,23 +24,20 @@ ## Development Workflow -We use `just` as a task runner. Available commands: +We use `poe` as a task runner. Available commands: ```bash # Run all checks -uv run just check +uv run poe check # Format code -uv run just format - -# Run type checking -uv run just typecheck +uv run poe format # Run tests -uv run just test +uv run poe test # Run conformance tests -uv run just conformance +uv run poe test-conformance ``` ## Code Style @@ -58,7 +55,7 @@ The project follows strict type checking and formatting standards. ### Unit Tests ```bash -uv run just test +uv run poe test ``` ### Conformance Tests @@ -66,7 +63,7 @@ uv run just test The project uses the official Connect conformance test suite. Go must be installed to run them. ```bash -uv run just conformance +uv run poe test-conformance ``` ## Code Generation @@ -74,7 +71,7 @@ uv run just conformance The project includes protobuf code generation for examples and tests: ```bash -uv run just generate +uv run poe generate ``` ## Releasing @@ -90,7 +87,7 @@ Documentation is contained in the [connectrpc/connectrpc.com](https://github.com 1. Fork the repository 2. Create a feature branch 3. Make your changes -4. Run the full test suite: `uv run just check` +4. Run the full smoke check suite: `uv run poe check` 5. Submit a pull request ### Pull Request Guidelines diff --git a/README.md b/README.md index b6854fe..c025cf0 100644 --- a/README.md +++ b/README.md @@ -408,8 +408,7 @@ Set up a virtual env: uv sync ``` -Then, use `uv run just` to do development checks, or check out `uv run just --list` for other targets. -`just` is run via `uv` as a development dependency, but you can also install it globally and omit the `uv run` from the commands. +Then, use `uv run poe check` to do development checks, or check out `uv run poe` for other targets. ## Status diff --git a/RELEASE.md b/RELEASE.md index be978e0..d6f7ed8 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -6,8 +6,8 @@ This document outlines how to create a release of connect-python. 2. On a new branch, update version strings with the `bump` command, either to the next minor or patch version, based on the changes that are included in this new release. -- If there are only bug fixes and no new features, run `uv run just bump patch`. -- If there are features being released, run `uv run just bump minor`. +- If there are only bug fixes and no new features, run `uv run poe bump --version patch`. +- If there are features being released, run `uv run poe bump --version minor`. Note the new version X.Y.Z in the updated files. diff --git a/connect-python.code-workspace b/connect-python.code-workspace index 01c93ab..79cd208 100644 --- a/connect-python.code-workspace +++ b/connect-python.code-workspace @@ -26,7 +26,6 @@ "golang.go", "ms-python.python", "ms-python.vscode-pylance", - "nefrob.vscode-just-syntax", ], }, "settings": { diff --git a/justfile b/justfile deleted file mode 100644 index 4625ef7..0000000 --- a/justfile +++ /dev/null @@ -1,73 +0,0 @@ -# https://just.systems/ - -BUF_VERSION := "v1.57.0" - -[private] -@default: check - -# Format Python files and TOML files -format: - uv run ruff check --fix --unsafe-fixes --exit-zero . - uv run ruff format . - uv run tombi format - -# Lint Python and TOML files -lint: - uv run ruff format --check . - uv run ruff check . - uv run tombi format --check - uv run tombi lint - -# Typecheck Python files -typecheck: - uv run pyright - -# Run unit tests -test *args: - uv run pytest {{ args }} - -# Run lint, typecheck and test -check: lint typecheck test - -# Run conformance tests -[working-directory('conformance')] -conformance *args: - uv run pytest {{ args }} - -# Generate gRPC status -generate-status: - go run github.com/bufbuild/buf/cmd/buf@{{ BUF_VERSION }} generate - -# Generate conformance files -[working-directory('conformance')] -generate-conformance: - go run github.com/bufbuild/buf/cmd/buf@{{ BUF_VERSION }} generate - @# We use the published conformance protos for tests, but need to make sure their package doesn't start with connectrpc - @# which conflicts with the runtime package. Since protoc python plugin does not provide a way to change the package - @# structure, we use sed to fix the imports instead. - LC_ALL=c find test/gen -type f -exec sed -i '' 's/from connectrpc.conformance.v1/from gen.connectrpc.conformance.v1/' {} + - -# Generate example files -[working-directory('example')] -generate-example: - go run github.com/bufbuild/buf/cmd/buf@{{ BUF_VERSION }} generate - -# Generate test files -[working-directory('test')] -generate-test: - go run github.com/bufbuild/buf/cmd/buf@{{ BUF_VERSION }} generate - -# Run all generation targets, and format the generated code -generate: generate-conformance generate-example generate-status generate-test format - -# Used in CI to verify that `just generate` doesn't produce a diff -checkgenerate: generate - test -z "$(git status --porcelain | tee /dev/stderr)" - -# Bump the version based on the given semver change (e.g., `minor` or `patch`). -bump semver: - uv version --bump={{ semver }} - uv version --bump={{ semver }} --directory protoc-gen-connect-python - -serve-docs: - uv run --group docs zensical serve diff --git a/poe_tasks.toml b/poe_tasks.toml new file mode 100644 index 0000000..0796981 --- /dev/null +++ b/poe_tasks.toml @@ -0,0 +1,116 @@ +#:schema https://json.schemastore.org/partial-poe.json + +[env] +BUF_VERSION = "v1.67.0" + +[tasks.bump] +help = "Bump the project version" +sequence = [ + { cmd = "uv version --active --bump=${_version}" }, + { cmd = "uv version --active --directory protoc-gen-connect-python --bump=${_version}" } +] +args = [ + { name = "_version", help = "The type of version bump to apply", choices = [ + "patch", + "minor", + "major" + ] } +] + +[tasks.check] +help = "Run smoke checks" +sequence = ["lint", "test", "test-otel"] + +[tasks.checkgenerate] +help = "Used in CI to verify that generate doesn't produce a diff" +sequence = [ + "generate", + { shell = 'test -z "$(git status --porcelain | tee /dev/stderr)"' }, +] + +[tasks.docs-build] +help = "Build documentation" +cmd = "zensical build" +executor = { type = "uv", group = "docs" } + +[tasks.docs-serve] +help = "Start documentation local server" +cmd = "zensical serve" +executor = { type = "uv", group = "docs" } + +[tasks.format] +help = "Apply all possible auto-formatting to files" +sequence = ["format-python", "format-toml"] + +[tasks.format-python] +help = "Apply auto-formatting to Python files" +sequence = [ + { cmd = "ruff check --fix --unsafe-fixes --exit-zero" }, + { cmd = "ruff format" } +] + +[tasks.format-toml] +help = "Apply auto-formatting to TOML files" +cmd = "tombi format" + +[tasks.generate] +help = "Generate all files" +sequence = [ + "generate-conformance", + "generate-example", + "generate-status", + "generate-test", + "format", +] + +[tasks.generate-conformance] +help = "Generate conformance files" +sequence = [ + { cmd = "go run github.com/bufbuild/buf/cmd/buf@${BUF_VERSION} generate" }, + { shell = "find test/gen -type f -exec sed -i '' 's/from connectrpc.conformance.v1/from gen.connectrpc.conformance.v1/' {} +", env = { "LC_ALL" = "c" } }, +] +cwd = "conformance" + +[tasks.generate-example] +help = "Generate example files" +cmd = "go run github.com/bufbuild/buf/cmd/buf@${BUF_VERSION} generate" +cwd = "example" + +[tasks.generate-status] +help = "Generate gRPC status" +cmd = "go run github.com/bufbuild/buf/cmd/buf@${BUF_VERSION} generate" + +[tasks.generate-test] +help = "Generate test files" +cmd = "go run github.com/bufbuild/buf/cmd/buf@${BUF_VERSION} generate" +cwd = "test" + +[tasks.lint] +help = "Apply all possible linting to files" +sequence = ["lint-python", "lint-toml", "lint-types"] + +[tasks.lint-python] +help = "Apply linting to Python files" +sequence = [{ cmd = "ruff check" }, { cmd = "ruff format --check" }] + +[tasks.lint-toml] +help = "Apply linting to TOML files" +cmd = "tombi lint" + +[tasks.lint-types] +help = "Apply type checking to Python files" +cmd = "pyright" + +[tasks.test] +help = "Run unit tests" +cmd = "pytest" + +[tasks.test-conformance] +help = "Run conformance tests. These are very slow" +cmd = "pytest" +cwd = "conformance" + +[tasks.test-otel] +help = "Run connectrpc-otel tests" +cmd = "pytest" +cwd = "connectrpc-otel" diff --git a/pyproject.toml b/pyproject.toml index 8fd3542..ab6555d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,7 @@ dev = [ "grpcio-tools==1.80.0", "gunicorn==25.3.0", "hypercorn==0.18.0", - "just-bin==1.48.1; sys_platform != 'win32'", + "poethepoet==0.44.0", "pyright[nodejs]==1.1.408", "pyvoy==0.3.0", "ruff==0.15.9", diff --git a/uv.lock b/uv.lock index d7c0f90..bb24abd 100644 --- a/uv.lock +++ b/uv.lock @@ -381,10 +381,10 @@ dev = [ { name = "grpcio-tools" }, { name = "gunicorn" }, { name = "hypercorn" }, - { name = "just-bin", marker = "sys_platform != 'win32'" }, { name = "opentelemetry-instrumentation-asgi" }, { name = "opentelemetry-instrumentation-wsgi" }, { name = "opentelemetry-sdk" }, + { name = "poethepoet" }, { name = "pyright", extra = ["nodejs"] }, { name = "pytest" }, { name = "pytest-asyncio" }, @@ -419,10 +419,10 @@ dev = [ { name = "grpcio-tools", specifier = "==1.80.0" }, { name = "gunicorn", specifier = "==25.3.0" }, { name = "hypercorn", specifier = "==0.18.0" }, - { name = "just-bin", marker = "sys_platform != 'win32'", specifier = "==1.48.1" }, { name = "opentelemetry-instrumentation-asgi", specifier = "==0.61b0" }, { name = "opentelemetry-instrumentation-wsgi", specifier = "==0.61b0" }, { name = "opentelemetry-sdk", specifier = "==1.40.0" }, + { name = "poethepoet", specifier = "==0.44.0" }, { name = "pyright", extras = ["nodejs"], specifier = "==1.1.408" }, { name = "pytest" }, { name = "pytest-asyncio" }, @@ -683,7 +683,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1097,17 +1097,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] -[[package]] -name = "just-bin" -version = "1.48.1" -source = { registry = "https://pypi.org/simple" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/d9/c17a1a7ca69315caa5153766bb7fb1558b187b1d6bb44e59da4e409c09db/just_bin-1.48.1-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:47adad09dad22a5414b5600ba6349da009f98b175a392352e0e6c606e8628841", size = 1858506, upload-time = "2026-03-30T16:16:49.174Z" }, - { url = "https://files.pythonhosted.org/packages/0d/a3/02cd3661cf3b8895ad8c0309945f187900743f7772a927fd435dc65bb404/just_bin-1.48.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d3a107ed0cff5057ab45775ded37b1d732246f4fba9b2fd7e9ccceb324041de8", size = 1711499, upload-time = "2026-03-30T16:16:50.843Z" }, - { url = "https://files.pythonhosted.org/packages/78/1d/74c8c0bc5ace0e29f195fd5e79f04b1a7519fca06ceb7f24508353bccb18/just_bin-1.48.1-py3-none-manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:c49be237a63acc45296bc58d8397fa6505e65044dd8cc1283c815ca8f25eccb7", size = 1855755, upload-time = "2026-03-30T16:16:52.131Z" }, - { url = "https://files.pythonhosted.org/packages/13/f0/57d95c26e01e72e572249472edf26017e96ca2bb10fabe52be1ea68cf1b7/just_bin-1.48.1-py3-none-manylinux2014_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:1738656d4c20d39a255a03d1c29d51269a59f85d74776f6c35da8ade3086a7a2", size = 2035778, upload-time = "2026-03-30T16:16:53.569Z" }, -] - [[package]] name = "markdown" version = "3.10.2" @@ -1485,6 +1474,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, ] +[[package]] +name = "pastel" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/f1/4594f5e0fcddb6953e5b8fe00da8c317b8b41b547e2b3ae2da7512943c62/pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d", size = 7555, upload-time = "2020-09-16T19:21:12.43Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/18/a8444036c6dd65ba3624c63b734d3ba95ba63ace513078e1580590075d21/pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364", size = 5955, upload-time = "2020-09-16T19:21:11.409Z" }, +] + [[package]] name = "pathspec" version = "1.0.4" @@ -1512,6 +1510,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] +[[package]] +name = "poethepoet" +version = "0.44.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pastel" }, + { name = "pyyaml" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/a4/e487662f12a5ecd2ac4d77f7697e4bda481953bb80032b158e5ab55173d4/poethepoet-0.44.0.tar.gz", hash = "sha256:c2667b513621788fb46482e371cdf81c0b04344e0e0bcb7aa8af45f84c2fce7b", size = 96040, upload-time = "2026-04-06T19:40:58.908Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/80/b7/503b7d3a51b0de9a329f1323048d166e309a97bb31bdc60e6acd11d2c71f/poethepoet-0.44.0-py3-none-any.whl", hash = "sha256:36d3d834708ed069ac1e4f8ed77915c55265b7b6e01aeb2fe617c9fe9cfd524a", size = 122873, upload-time = "2026-04-06T19:40:57.369Z" }, +] + [[package]] name = "priority" version = "1.3.0" @@ -1938,8 +1950,8 @@ name = "taskgroup" version = "0.2.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "exceptiongroup" }, - { name = "typing-extensions" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f0/8d/e218e0160cc1b692e6e0e5ba34e8865dbb171efeb5fc9a704544b3020605/taskgroup-0.2.2.tar.gz", hash = "sha256:078483ac3e78f2e3f973e2edbf6941374fbea81b9c5d0a96f51d297717f4752d", size = 11504, upload-time = "2025-01-03T09:24:13.761Z" } wheels = [ From a6207c8e5484d5312471b2613fa320adfcc3b20c Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Tue, 7 Apr 2026 14:50:44 +0900 Subject: [PATCH 2/4] Fix working directory Signed-off-by: Anuraag Agrawal --- .github/workflows/ci.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7165f56..127c2de 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -83,7 +83,6 @@ jobs: - name: run OTel tests run: uv run poe test-otel ${{ matrix.coverage == 'cov' && '--cov=connectrpc_otel --cov-report=xml' || '' }} - working-directory: connectrpc-otel - name: run Go tests run: go test ./... From 2ee893254acd32f373b1d3ccd1917fb7b2ef96cd Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Tue, 7 Apr 2026 14:55:10 +0900 Subject: [PATCH 3/4] Build before otel Signed-off-by: Anuraag Agrawal --- poe_tasks.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/poe_tasks.toml b/poe_tasks.toml index 0796981..e537d18 100644 --- a/poe_tasks.toml +++ b/poe_tasks.toml @@ -112,5 +112,7 @@ cwd = "conformance" [tasks.test-otel] help = "Run connectrpc-otel tests" -cmd = "pytest" +# Use uv run to make sure the package is built before running tests. +# Instrumentation tests require package metadata. +cmd = "uv run pytest" cwd = "connectrpc-otel" From 586d13208a7f89afcb114b7d39f5b3d0204dea45 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Tue, 7 Apr 2026 15:08:42 +0900 Subject: [PATCH 4/4] go bump Signed-off-by: Anuraag Agrawal --- protoc-gen-connect-python/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protoc-gen-connect-python/go.mod b/protoc-gen-connect-python/go.mod index a2bbf60..d938cc1 100644 --- a/protoc-gen-connect-python/go.mod +++ b/protoc-gen-connect-python/go.mod @@ -1,6 +1,6 @@ module github.com/connectrpc/connect-python/protoc-gen-connect-python -go 1.25.0 +go 1.25.7 require ( github.com/bufbuild/protoplugin v0.0.0-20250218205857-750e09ce93e1