Skip to content

Commit 5ee48c5

Browse files
committed
Merge remote-tracking branch 'origin/master' into err/in_app_configuration
2 parents 6708a97 + 80e6e43 commit 5ee48c5

26 files changed

+2739
-241
lines changed

.github/workflows/generate-references.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ jobs:
77
docs-generation:
88
name: Generate references
99
runs-on: ubuntu-latest
10+
permissions:
11+
contents: write
1012
steps:
1113
- name: Checkout the repository
1214
uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2
1315
with:
1416
fetch-depth: 0
15-
token: ${{ secrets.POSTHOG_BOT_PAT }}
1617

1718
- name: Set up Python
1819
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55

.github/workflows/release.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@ jobs:
1212
release:
1313
name: Publish release
1414
runs-on: ubuntu-latest
15-
env:
16-
TWINE_USERNAME: __token__
17-
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
15+
permissions:
16+
contents: write
17+
id-token: write
1818
steps:
1919
- name: Checkout the repository
2020
uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2
2121
with:
2222
fetch-depth: 0
23-
token: ${{ secrets.POSTHOG_BOT_PAT }}
2423

2524
- name: Set up Python
2625
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55
@@ -40,12 +39,12 @@ jobs:
4039
run: uv sync --extra dev
4140

4241
- name: Push releases to PyPI
42+
env:
43+
TWINE_USERNAME: __token__
4344
run: uv run make release && uv run make release_analytics
4445

4546
- name: Create GitHub release
4647
uses: actions/create-release@0cb9c9b65d5d1901c1f53e5e66eaf4afd303e70e # v1
47-
env:
48-
GITHUB_TOKEN: ${{ secrets.POSTHOG_BOT_PAT }}
4948
with:
5049
tag_name: v${{ env.REPO_VERSION }}
5150
release_name: ${{ env.REPO_VERSION }}

CHANGELOG.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
1-
# 7.2.1 - 2025-12-19
1+
# 7.4.1 - 2025-12-19
22

33
feat: add `in_app_modules` option to control code variables capturing
44

5+
# 7.4.0 - 2025-12-16
6+
7+
feat: Add automatic retries for feature flag requests
8+
9+
Feature flag API requests now automatically retry on transient failures:
10+
- Network errors (connection refused, DNS failures, timeouts)
11+
- Server errors (500, 502, 503, 504)
12+
- Up to 2 retries with exponential backoff (0.5s, 1s delays)
13+
14+
Rate limit (429) and quota (402) errors are not retried.
15+
16+
# 7.3.1 - 2025-12-06
17+
18+
fix: remove unused $exception_message and $exception_type
19+
20+
# 7.3.0 - 2025-12-05
21+
22+
feat: improve code variables capture masking
23+
524
# 7.2.0 - 2025-12-01
625

726
feat: add $feature_flag_evaluated_at properties to $feature_flag_called events

example.py

Lines changed: 67 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -35,54 +35,40 @@ def load_env_file():
3535
personal_api_key = os.getenv("POSTHOG_PERSONAL_API_KEY", "")
3636
host = os.getenv("POSTHOG_HOST", "http://localhost:8000")
3737

38-
# Check if credentials are provided
39-
if not project_key or not personal_api_key:
40-
print("❌ Missing PostHog credentials!")
41-
print(
42-
" Please set POSTHOG_PROJECT_API_KEY and POSTHOG_PERSONAL_API_KEY environment variables"
43-
)
38+
# Check if project key is provided (required)
39+
if not project_key:
40+
print("❌ Missing PostHog project API key!")
41+
print(" Please set POSTHOG_PROJECT_API_KEY environment variable")
4442
print(" or copy .env.example to .env and fill in your values")
4543
exit(1)
4644

47-
# Test authentication before proceeding
48-
print("🔑 Testing PostHog authentication...")
45+
# Configure PostHog with credentials
46+
posthog.debug = False
47+
posthog.api_key = project_key
48+
posthog.project_api_key = project_key
49+
posthog.host = host
50+
posthog.poll_interval = 10
4951

50-
try:
51-
# Configure PostHog with credentials
52-
posthog.debug = False # Keep quiet during auth test
53-
posthog.api_key = project_key
54-
posthog.project_api_key = project_key
52+
# Check if personal API key is available for local evaluation
53+
local_eval_available = bool(personal_api_key)
54+
if personal_api_key:
5555
posthog.personal_api_key = personal_api_key
56-
posthog.host = host
57-
posthog.poll_interval = 10
58-
59-
# Test by attempting to get feature flags (this validates both keys)
60-
# This will fail if credentials are invalid
61-
test_flags = posthog.get_all_flags("test_user", only_evaluate_locally=True)
62-
63-
# If we get here without exception, credentials work
64-
print("✅ Authentication successful!")
65-
print(f" Project API Key: {project_key[:9]}...")
66-
print(" Personal API Key: [REDACTED]")
67-
print(f" Host: {host}\n\n")
68-
69-
except Exception as e:
70-
print("❌ Authentication failed!")
71-
print(f" Error: {e}")
72-
print("\n Please check your credentials:")
73-
print(" - POSTHOG_PROJECT_API_KEY: Project API key from PostHog settings")
74-
print(
75-
" - POSTHOG_PERSONAL_API_KEY: Personal API key (required for local evaluation)"
76-
)
77-
print(" - POSTHOG_HOST: Your PostHog instance URL")
78-
exit(1)
56+
57+
print("🔑 PostHog Configuration:")
58+
print(f" Project API Key: {project_key[:9]}...")
59+
if local_eval_available:
60+
print(" Personal API Key: [SET]")
61+
else:
62+
print(" Personal API Key: [NOT SET] - Local evaluation examples will be skipped")
63+
print(f" Host: {host}\n")
7964

8065
# Display menu and get user choice
8166
print("🚀 PostHog Python SDK Demo - Choose an example to run:\n")
8267
print("1. Identify and capture examples")
83-
print("2. Feature flag local evaluation examples")
68+
local_eval_note = "" if local_eval_available else " [requires personal API key]"
69+
print(f"2. Feature flag local evaluation examples{local_eval_note}")
8470
print("3. Feature flag payload examples")
85-
print("4. Flag dependencies examples")
71+
print(f"4. Flag dependencies examples{local_eval_note}")
8672
print("5. Context management and tagging examples")
8773
print("6. Run all examples")
8874
print("7. Exit")
@@ -148,6 +134,14 @@ def load_env_file():
148134
)
149135

150136
elif choice == "2":
137+
if not local_eval_available:
138+
print("\n❌ This example requires a personal API key for local evaluation.")
139+
print(
140+
" Set POSTHOG_PERSONAL_API_KEY environment variable to run this example."
141+
)
142+
posthog.shutdown()
143+
exit(1)
144+
151145
print("\n" + "=" * 60)
152146
print("FEATURE FLAG LOCAL EVALUATION EXAMPLES")
153147
print("=" * 60)
@@ -215,6 +209,14 @@ def load_env_file():
215209
print(f"Value (variant or enabled): {result.get_value()}")
216210

217211
elif choice == "4":
212+
if not local_eval_available:
213+
print("\n❌ This example requires a personal API key for local evaluation.")
214+
print(
215+
" Set POSTHOG_PERSONAL_API_KEY environment variable to run this example."
216+
)
217+
posthog.shutdown()
218+
exit(1)
219+
218220
print("\n" + "=" * 60)
219221
print("FLAG DEPENDENCIES EXAMPLES")
220222
print("=" * 60)
@@ -429,6 +431,8 @@ def process_payment(payment_id):
429431

430432
elif choice == "6":
431433
print("\n🔄 Running all examples...")
434+
if not local_eval_available:
435+
print(" (Skipping local evaluation examples - no personal API key set)\n")
432436

433437
# Run example 1
434438
print(f"\n{'🔸' * 20} IDENTIFY AND CAPTURE {'🔸' * 20}")
@@ -447,35 +451,37 @@ def process_payment(payment_id):
447451
distinct_id="new_distinct_id", properties={"email": "[email protected]"}
448452
)
449453

450-
# Run example 2
451-
print(f"\n{'🔸' * 20} FEATURE FLAGS {'🔸' * 20}")
452-
print("🏁 Testing basic feature flags...")
453-
print(f"beta-feature: {posthog.feature_enabled('beta-feature', 'distinct_id')}")
454-
print(
455-
f"Sydney user: {posthog.feature_enabled('test-flag', 'random_id_12345', person_properties={'$geoip_city_name': 'Sydney'})}"
456-
)
454+
# Run example 2 (requires local evaluation)
455+
if local_eval_available:
456+
print(f"\n{'🔸' * 20} FEATURE FLAGS {'🔸' * 20}")
457+
print("🏁 Testing basic feature flags...")
458+
print(f"beta-feature: {posthog.feature_enabled('beta-feature', 'distinct_id')}")
459+
print(
460+
f"Sydney user: {posthog.feature_enabled('test-flag', 'random_id_12345', person_properties={'$geoip_city_name': 'Sydney'})}"
461+
)
457462

458463
# Run example 3
459464
print(f"\n{'🔸' * 20} PAYLOADS {'🔸' * 20}")
460465
print("📦 Testing payloads...")
461466
print(f"Payload: {posthog.get_feature_flag_payload('beta-feature', 'distinct_id')}")
462467

463-
# Run example 4
464-
print(f"\n{'🔸' * 20} FLAG DEPENDENCIES {'🔸' * 20}")
465-
print("🔗 Testing flag dependencies...")
466-
result1 = posthog.feature_enabled(
467-
"test-flag-dependency",
468-
"demo_user",
469-
person_properties={"email": "[email protected]"},
470-
only_evaluate_locally=True,
471-
)
472-
result2 = posthog.feature_enabled(
473-
"test-flag-dependency",
474-
"demo_user2",
475-
person_properties={"email": "[email protected]"},
476-
only_evaluate_locally=True,
477-
)
478-
print(f"✅ @example.com user: {result1}, regular user: {result2}")
468+
# Run example 4 (requires local evaluation)
469+
if local_eval_available:
470+
print(f"\n{'🔸' * 20} FLAG DEPENDENCIES {'🔸' * 20}")
471+
print("🔗 Testing flag dependencies...")
472+
result1 = posthog.feature_enabled(
473+
"test-flag-dependency",
474+
"demo_user",
475+
person_properties={"email": "[email protected]"},
476+
only_evaluate_locally=True,
477+
)
478+
result2 = posthog.feature_enabled(
479+
"test-flag-dependency",
480+
"demo_user2",
481+
person_properties={"email": "[email protected]"},
482+
only_evaluate_locally=True,
483+
)
484+
print(f"✅ @example.com user: {result1}, regular user: {result2}")
479485

480486
# Run example 5
481487
print(f"\n{'🔸' * 20} CONTEXT MANAGEMENT {'🔸' * 20}")

0 commit comments

Comments
 (0)