Skip to content

fix: derive sub-package __version__ from a single source of truth#182

Open
KomanRudden wants to merge 7 commits into
mainfrom
fix/sub-package-version-drift
Open

fix: derive sub-package __version__ from a single source of truth#182
KomanRudden wants to merge 7 commits into
mainfrom
fix/sub-package-version-drift

Conversation

@KomanRudden

@KomanRudden KomanRudden commented May 22, 2026

Copy link
Copy Markdown
Contributor

Makes kinde_sdk/_version.py the source of truth for the SDK version: the top-level package, both generated sub-packages, and pyproject.toml now all derive from it.
Generator scripts read the same value to set packageVersion, and bumps the SDK to 2.3.0.
Adds a regression test that fail if any of those four versions ever go out of sync.

Checklist

🛟 If you need help, consider asking for advice over in the Kinde community.

The OpenAPI-generated kinde_sdk.management and kinde_sdk.frontend
sub-packages have been emitting __version__ = "2.0.0" since the 2.x
line was cut, regardless of what the SDK is actually shipped as. The
2.3.0 wheel on PyPI demonstrates the drift: kinde_sdk.__version__ is
"2.3.0" but kinde_sdk.management.__version__ and
kinde_sdk.frontend.__version__ both report "2.0.0".

Root cause: packageVersion was hard-coded across both generator
scripts and their config files. Every regeneration wrote the stale
value back into the sub-package __init__.py files, and bumping the
top-level SDK didn't propagate.

This change introduces a single source of truth and keeps the
generated sub-packages dynamically in sync, so the literal version
no longer appears in any sub-package __init__.py at all.

Changes:
- New kinde_sdk/_version.py contains the only literal version string
  in the SDK. It has zero imports so it can be safely re-exported from
  any sub-package without risking a circular import.
- kinde_sdk/__init__.py re-exports __version__ from _version.
- kinde_sdk/management/__init__.py and kinde_sdk/frontend/__init__.py
  now do the same: `from kinde_sdk._version import __version__`.
  No literal version string in either file - cannot drift.
- generate_management_sdk.py and generate_frontend_sdk.py both gain a
  make_version_dynamic() post-generation step that rewrites the
  OpenAPI-emitted `__version__ = "X"` line back to the import on
  every regeneration. Idempotent: a no-op if already rewritten.
- Both generator scripts still derive packageVersion from
  kinde_sdk._version (via _read_sdk_version) so other generated
  artifacts that embed the version literally - notably user-agent
  headers in the generated configuration.py - also stay in lockstep.
- generate_frontend_sdk.py now (re)writes generator/frontend_config.yaml
  on every run rather than only when missing, so a stale local config
  can no longer silently override the SDK version.
- openapitools.json packageVersion bumped to 2.2.0 to match today's
  SDK version. This file is overwritten by generate_management_sdk.py
  on every run from kinde_sdk._version, so it stays in sync going
  forward; the bump just brings the checked-in config into agreement.

Going forward, bump kinde_sdk/_version.py and you're done -
kinde_sdk.__version__, kinde_sdk.management.__version__,
kinde_sdk.frontend.__version__, and importlib.metadata all report the
new value, with no need to touch any sub-package __init__.py.

Verified end-to-end in a clean venv (pip install -e .): all three
namespaces resolve to the same __version__ object, no circular import.

Made-with: Cursor
@KomanRudden KomanRudden requested a review from a team as a code owner May 22, 2026 03:54
@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@KomanRudden, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 49 minutes and 18 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e3d09a77-2825-4907-bbcb-6aea32e25a17

📥 Commits

Reviewing files that changed from the base of the PR and between dd3e1e5 and 02da024.

📒 Files selected for processing (1)
  • _sdk_generator_utils.py

Walkthrough

Centralizes SDK version in kinde_sdk/_version.py, re-exports it from package inits, makes both OpenAPI generator configs use a packageVersion placeholder with resolved SDK injection at CLI runtime, rewrites generated init.py files to import the canonical version, and adds tests asserting synchronization.

Changes

Version consolidation to single source of truth

Layer / File(s) Summary
Canonical version source
kinde_sdk/_version.py
Replaces the module header with documentation and sets the canonical __version__ = "2.3.0".
Package version imports
kinde_sdk/__init__.py, kinde_sdk/management/__init__.py
Both packages now import/re-export __version__ from kinde_sdk._version instead of embedding literal strings.
Frontend generator version sync
generate_frontend_sdk.py
Adds _read_sdk_version() and make_version_dynamic(), writes generator/frontend_config.yaml with a packageVersion placeholder, injects the resolved SDK version into the OpenAPI CLI via --additional-properties=packageVersion=..., and rewrites generated kinde_sdk/frontend/__init__.py to import the canonical version.
Management generator version sync
generate_management_sdk.py
Adds SDK-version helpers, treats openapitools.json packageVersion as a placeholder template, injects SDK_VERSION at CLI runtime, and rewrites the generated management __init__.py to import the canonical __version__.
Tests and .gitignore
testv2/testv2_core/test_version_sync.py, .gitignore
Adds tests that assert all package versions and generator config placeholders match the canonical version; updates .gitignore to ignore local .env* files while allowing example files.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: establishing a single source of truth for SDK versioning across subpackages.
Description check ✅ Passed The description directly addresses the changeset by explaining the versioning consolidation strategy, generator script updates, and testing approach.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sub-package-version-drift

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented May 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
generate_frontend_sdk.py (1)

241-254: 💤 Low value

Minor: Comment references wrong source file.

Line 243 states packageVersion is derived from kinde_sdk/__init__.py's __version__, but the generator actually reads from kinde_sdk/_version.py directly via _read_sdk_version(). Consider updating the comment for accuracy.

📝 Suggested fix
-# packageVersion is derived from kinde_sdk/__init__.py's __version__.
+# packageVersion is derived from kinde_sdk/_version.py's __version__.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@generate_frontend_sdk.py` around lines 241 - 254, Comment in
generate_frontend_sdk.py incorrectly states the packageVersion is derived from
kinde_sdk/__init__.py; update that comment to reference kinde_sdk/_version.py
(or the _read_sdk_version() helper) and/or say it is derived from SDK_VERSION
which is populated by _read_sdk_version(), so the config header using
CONFIG_FILE and packageVersion: {SDK_VERSION} accurately documents the source.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@generate_frontend_sdk.py`:
- Around line 241-254: Comment in generate_frontend_sdk.py incorrectly states
the packageVersion is derived from kinde_sdk/__init__.py; update that comment to
reference kinde_sdk/_version.py (or the _read_sdk_version() helper) and/or say
it is derived from SDK_VERSION which is populated by _read_sdk_version(), so the
config header using CONFIG_FILE and packageVersion: {SDK_VERSION} accurately
documents the source.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 37baef7a-7643-463f-9f09-4b4e6142ec0f

📥 Commits

Reviewing files that changed from the base of the PR and between 05f4ce5 and 6f4e060.

⛔ Files ignored due to path filters (2)
  • kinde_sdk/frontend/__init__.py is excluded by !kinde_sdk/frontend/**
  • openapitools.json is excluded by !**/*.json
📒 Files selected for processing (5)
  • generate_frontend_sdk.py
  • generate_management_sdk.py
  • kinde_sdk/__init__.py
  • kinde_sdk/_version.py
  • kinde_sdk/management/__init__.py

@KomanRudden KomanRudden requested a review from a team as a code owner May 22, 2026 04:11

@dtoxvanilla1991 dtoxvanilla1991 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good work, left some comments.

Comment thread openapitools.json Outdated
Comment thread pyproject.toml
Comment thread poetry.lock Outdated
Comment thread generate_frontend_sdk.py Outdated
Comment thread generate_management_sdk.py Outdated
Comment thread generate_frontend_sdk.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@testv2/testv2_core/test_version_sync.py`:
- Around line 53-67: The test test_distribution_metadata_matches_source_of_truth
currently skips entirely when dist_version("kinde-python-sdk") raises
PackageNotFoundError; instead, preserve the installed-metadata assertion path
but change the except block to read the version from pyproject.toml and assert
it equals kinde_sdk._version (i.e., don't call pytest.skip on
PackageNotFoundError); use dist_version for the installed case, and in the
fallback parse pyproject.toml (or use tomlkit/pip's metadata API) to extract the
version string and compare it to kinde_sdk._version so drift is detected in raw
checkouts as well.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0f61f49c-2634-4450-9592-ae5f84923311

📥 Commits

Reviewing files that changed from the base of the PR and between 6f4e060 and c950528.

⛔ Files ignored due to path filters (3)
  • openapitools.json is excluded by !**/*.json
  • poetry.lock is excluded by !**/*.lock, !**/*.lock
  • pyproject.toml is excluded by !**/*.toml
📒 Files selected for processing (5)
  • .gitignore
  • generate_frontend_sdk.py
  • generate_management_sdk.py
  • kinde_sdk/_version.py
  • testv2/testv2_core/test_version_sync.py
✅ Files skipped from review due to trivial changes (1)
  • .gitignore

Comment thread testv2/testv2_core/test_version_sync.py

@dtoxvanilla1991 dtoxvanilla1991 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

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.

2 participants