Skip to content

Commit cf07c2f

Browse files
committed
chore: Make samples default to use PyPI for the SDK
1 parent 030ba23 commit cf07c2f

4 files changed

Lines changed: 38 additions & 12 deletions

File tree

.github/workflows/ci.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,5 +91,9 @@ jobs:
9191
with:
9292
enable-cache: true
9393

94-
# Each sample resolves the SDK by local path, so it is not locked against a release.
94+
# Each sample pins a released SDK from PyPI, so this checks the published wheel.
9595
- run: make samples
96+
97+
# And again against this working tree, which is what catches a breaking API change before
98+
# it ships. Both matter: the first can fail on a bad release, the second on a bad commit.
99+
- run: make samples-local

Makefile

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: install hooks lint format typecheck test coverage build verify-lock dist-check samples profile check check-all clean
1+
.PHONY: install hooks lint format typecheck test coverage build verify-lock dist-check samples samples-local profile check check-all clean
22

33
install:
44
uv sync --all-extras
@@ -50,14 +50,32 @@ dist-check: build
5050
"import configdirector; print('wheel imports cleanly:', configdirector.__version__)"; \
5151
status=$$?; rm -rf "$$tmp"; exit $$status
5252

53-
# Samples resolve the SDK by local path, so this is what catches a breaking API change.
53+
# Samples resolve the SDK from PyPI, so this checks the published release against the sample
54+
# code -- it does NOT exercise the working tree, and will not catch a breaking API change here.
5455
samples:
5556
@for sample in samples/*/; do \
5657
[ -f "$$sample/pyproject.toml" ] || continue; \
5758
printf '\n\033[1m==> sample %s\033[0m\n' "$$(basename $$sample)"; \
5859
(cd "$$sample" && uv sync --quiet && uv run mypy && uv run pytest) || exit 1; \
5960
done
6061

62+
# Companion to `samples`: the same apps, resolved against the SDK in this working tree instead
63+
# of the released wheel. `samples` proves the published release still works with the sample code;
64+
# this proves an unreleased API change has not broken it. Without this target a breaking change
65+
# passes every check, because the samples pin a version from PyPI.
66+
#
67+
# uv sync installs the pinned release, then the editable install replaces it in the same
68+
# environment, and --no-sync stops uv from undoing that before the checks run. The override is
69+
# not written to any file, so nothing here can be committed by accident; the next plain
70+
# `make samples` restores the released version.
71+
samples-local:
72+
@for sample in samples/*/; do \
73+
[ -f "$$sample/pyproject.toml" ] || continue; \
74+
printf '\n\033[1m==> sample %s (working-tree SDK)\033[0m\n' "$$(basename $$sample)"; \
75+
(cd "$$sample" && uv sync --quiet && uv pip install --quiet -e ../.. \
76+
&& uv run --no-sync mypy && uv run --no-sync pytest) || exit 1; \
77+
done
78+
6179
# Exploratory load profile of the Flask sample: see profiling/README.md. Deliberately not part
6280
# of `check-all` — it needs a real server SDK key, takes minutes, and measures the machine it
6381
# ran on as much as the SDK. Pass options through, e.g. `make profile ARGS="--rps 100"`.
@@ -69,7 +87,7 @@ profile:
6987
check: lint typecheck test
7088

7189
# Everything CI runs. The pre-push hook calls this.
72-
check-all: verify-lock lint typecheck test dist-check samples
90+
check-all: verify-lock lint typecheck test dist-check samples samples-local
7391
@printf '\n\033[1m✓ all checks passed\033[0m\n'
7492

7593
clean:

samples/README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,15 @@ different web frameworks.
77
|---|---|---|
88
| [flask/](flask/) | [Flask](https://flask.palletsprojects.com/) | Minimal WSGI app: client lifecycle, per-request evaluation, SSR hydration |
99

10-
Each sample is an independent project with its own `pyproject.toml`. They depend on the SDK
11-
through a local path (`configdirector-server-sdk = { path = "../.." }`) so that they always run
12-
against the working copy in this repository rather than a published release.
10+
Each sample is an independent project with its own `pyproject.toml`, depending on the released
11+
`configdirector-server-sdk` from PyPI exactly as a real app would. They do not run against the
12+
working copy in this repository; to try a local change in a sample, add a temporary source
13+
override to that sample and remove it before committing:
14+
15+
```toml
16+
[tool.uv.sources]
17+
configdirector-server-sdk = { path = "../..", editable = true }
18+
```
1319

1420
To run one:
1521

samples/flask/pyproject.toml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ version = "0.0.0"
44
description = "Flask sample app for the ConfigDirector Python server SDK"
55
requires-python = ">=3.10"
66
dependencies = [
7-
"configdirector-server-sdk",
7+
# Resolved from PyPI, like any consuming app would. The SDK is pre-1.0, so a 0.x minor is
8+
# allowed to break: cap the range rather than tracking the newest release blindly.
9+
"configdirector-server-sdk>=0.2,<0.3",
810
"flask>=3.1",
911
"python-dotenv>=1.0",
1012
]
@@ -16,10 +18,6 @@ dev = ["mypy>=1.14", "pytest>=8.3"]
1618
# A runnable app, not a distributable package: install the dependencies, not this project.
1719
package = false
1820

19-
[tool.uv.sources]
20-
# Always run against the SDK in this repository rather than a published release.
21-
configdirector-server-sdk = { path = "../..", editable = true }
22-
2321
[tool.ruff]
2422
# Inherit the SDK's style, but resolve first-party imports against this directory so that
2523
# `configdirector` sorts as the third-party dependency it is here.

0 commit comments

Comments
 (0)