Skip to content

Commit 90501fe

Browse files
ci: remove hardcoded version from _version.py via post_generate.py (#177)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent abdb7d7 commit 90501fe

6 files changed

Lines changed: 81 additions & 24 deletions

File tree

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Do not guess or iterate blindly. Download the artifact first.
1515
## Files You Can Safely Edit
1616

1717
- `overlays/python_speakeasy.yaml` — Speakeasy overlay
18-
- `scripts/post_generate.py` — Post-generation patch script
18+
- `scripts/post_generate.uv` — Post-generation patch script (standalone uv script)
1919
- `poe_tasks.toml` — Build task definitions
2020
- `.github/workflows/` — CI workflows
2121
- `.github/dependabot.yml` — Dependabot configuration

CONTRIBUTING.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ The Python SDK is generated through a multi-step pipeline:
2929
3030
┌──────────────────────────────────────────┐
3131
│ 4. Post-Generation Patches │
32-
│ (scripts/post_generate.py) │
32+
│ (scripts/post_generate.uv) │
3333
└──────────────────┬───────────────────────┘
3434
3535
@@ -49,15 +49,15 @@ The Python SDK is generated through a multi-step pipeline:
4949

5050
3. **Speakeasy Code Generation** — Speakeasy consumes the spec (+ overlay if enabled) and generates the Python SDK in `src/airbyte_api/`. These files should never be edited by hand.
5151

52-
4. **Post-Generation Patches** — A Python script applies any SDK-specific patches after generation (currently a no-op placeholder):
53-
[`scripts/post_generate.py`](https://github.com/airbytehq/airbyte-api-python-sdk/blob/main/scripts/post_generate.py)
52+
4. **Post-Generation Patches** — A standalone uv script applies SDK-specific patches after generation (e.g. replacing the hardcoded `__version__` with `importlib.metadata`):
53+
[`scripts/post_generate.uv`](https://github.com/airbytehq/airbyte-api-python-sdk/blob/main/scripts/post_generate.uv)
5454

5555
5. **Package Build & Publish** — The generated SDK is built with `uv build` and published to PyPI via OIDC trusted publishing.
5656

5757
> **Tip:** If you need to change SDK behavior, determine which layer is appropriate:
5858
> - **API changes** → submit to the [upstream OpenAPI spec](https://github.com/airbytehq/airbyte-platform/blob/main/airbyte-api/server-api/src/main/openapi/api_sdk.yaml)
5959
> - **Python SDK-specific schema tweaks** → modify the [overlay](https://github.com/airbytehq/airbyte-api-python-sdk/blob/main/overlays/python_speakeasy.yaml)
60-
> - **Post-generation fixes** → modify the [post-generate script](https://github.com/airbytehq/airbyte-api-python-sdk/blob/main/scripts/post_generate.py)
60+
> - **Post-generation fixes** → modify the [post-generate script](https://github.com/airbytehq/airbyte-api-python-sdk/blob/main/scripts/post_generate.uv)
6161
> - Then trigger regeneration (see below)
6262
6363
## For Maintainers

poe_tasks.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ speakeasy run $ARGS
1313
[tasks._post-generate]
1414
help = "Run post-generation patches."
1515
shell = """
16-
uv run python scripts/post_generate.py
16+
uv run scripts/post_generate.uv
1717
"""
1818

1919
[tasks._generate-readme]

scripts/post_generate.py

Lines changed: 0 additions & 16 deletions
This file was deleted.

scripts/post_generate.uv

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env -S uv run --python 3.10 --script
2+
# /// script
3+
# requires-python = ">=3.10,<3.14"
4+
# dependencies = []
5+
# ///
6+
"""Post-generation patch pipeline.
7+
8+
Runs after Speakeasy code generation to apply durable fixes to generated code.
9+
See the terraform-provider-airbyte repo for more examples of post-generation patches.
10+
"""
11+
12+
import re
13+
from pathlib import Path
14+
15+
REPO_ROOT = Path(__file__).resolve().parent.parent
16+
VERSION_FILE = REPO_ROOT / "src" / "airbyte_api" / "_version.py"
17+
18+
19+
def patch_version_file() -> None:
20+
"""Replace the hardcoded `__version__` in `_version.py` with a dynamic lookup.
21+
22+
Speakeasy generates a `_version.py` with a hardcoded `__version__` string
23+
and a static `__user_agent__`. This patch rewrites both so that the
24+
installed package version (set at build time by `uv-dynamic-versioning`
25+
from the git tag) is used instead. Generation metadata
26+
(`__openapi_doc_version__`, `__gen_version__`) is left intact.
27+
"""
28+
text = VERSION_FILE.read_text()
29+
original = text
30+
31+
# 1. Replace the hardcoded __version__ assignment with importlib.metadata lookup.
32+
# Matches: __version__: str = "1.0.0" (any semver-ish string)
33+
text = re.sub(
34+
r'^__version__: str = ".*"$',
35+
"__version__: str = importlib.metadata.version(__title__)",
36+
text,
37+
count=1,
38+
flags=re.MULTILINE,
39+
)
40+
41+
# 2. Replace the static __user_agent__ string with an f-string using the
42+
# dynamic __version__.
43+
# Matches: __user_agent__: str = "speakeasy-sdk/python 1.0.0 2.911.0 1.0.0 airbyte-api"
44+
text = re.sub(
45+
r'^__user_agent__: str = "speakeasy-sdk/python .+"$',
46+
(
47+
"__user_agent__: str = (\n"
48+
' f"speakeasy-sdk/python {__version__} {__gen_version__}"\n'
49+
' f" {__openapi_doc_version__} {__title__}"\n'
50+
")"
51+
),
52+
text,
53+
count=1,
54+
flags=re.MULTILINE,
55+
)
56+
57+
if text == original:
58+
print("post_generate: _version.py already patched (no changes)")
59+
return
60+
61+
VERSION_FILE.write_text(text)
62+
print("post_generate: patched _version.py (hardcoded __version__ → importlib.metadata)")
63+
64+
65+
def main() -> None:
66+
patch_version_file()
67+
68+
69+
if __name__ == "__main__":
70+
main()

src/airbyte_api/_version.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
import importlib.metadata
44

55
__title__: str = "airbyte-api"
6-
__version__: str = "1.0.0"
6+
__version__: str = importlib.metadata.version(__title__)
77
__openapi_doc_version__: str = "1.0.0"
88
__gen_version__: str = "2.911.0"
9-
__user_agent__: str = "speakeasy-sdk/python 1.0.0 2.911.0 1.0.0 airbyte-api"
9+
__user_agent__: str = (
10+
f"speakeasy-sdk/python {__version__} {__gen_version__}"
11+
f" {__openapi_doc_version__} {__title__}"
12+
)
1013

1114
try:
1215
if __package__ is not None:

0 commit comments

Comments
 (0)