Skip to content

Commit 95d3542

Browse files
committed
Merge branch 'main' into gh-pages
2 parents 2508975 + af5de3a commit 95d3542

66 files changed

Lines changed: 4341 additions & 373 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/copilot-instructions.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# FEATURE MANAGEMENT FOR PYTHON - COPILOT INSTRUCTIONS
2+
3+
---
4+
5+
## CORE PRINCIPLES
6+
7+
### RULE 1: DO NOT REPEAT INSTRUCTIONS
8+
**NEVER repeat instructions when guiding users. Users should follow instructions independently.**
9+
10+
### RULE 2: REFERENCE OFFICIAL DOCUMENTATION
11+
**ALWAYS** reference the [Azure SDK Python Design Guidelines](https://azure.github.io/azure-sdk/python_design.html)
12+
- Link to specific pages when answering guidelines questions
13+
- Use this as the authoritative source for SDK development guidance
14+
15+
### RULE 3: VERIFY ENVIRONMENT FIRST
16+
**REQUIRED CONDITIONS:**
17+
- Always activate the Python virtual environment before running Python commands:
18+
- On Windows: `.venv\Scripts\activate`
19+
- On Linux/macOS: `source .venv/bin/activate`
20+
- Use `python -m pip` instead of bare `pip` when installing packages.
21+
22+
---
23+
24+
## DEV SETUP
25+
26+
Install all dependencies with:
27+
28+
```bash
29+
python -m pip install -e ".[dev,test]"
30+
```
31+
32+
This project requires **Python 3.10 or newer**.
33+
34+
---
35+
36+
## PROJECT STRUCTURE
37+
38+
- `featuremanagement/` — Synchronous feature management code
39+
- `featuremanagement/aio/` — Async equivalents of feature management classes
40+
- `featuremanagement/_models/` — Data models (feature flags, variants, telemetry)
41+
- `featuremanagement/_time_window_filter/` — Time window filter with recurrence support
42+
- `featuremanagement/azuremonitor/` — Optional Azure Monitor telemetry integration
43+
- `tests/` — Unit tests (sync and async)
44+
- `samples/` — Sample applications
45+
46+
---
47+
48+
## CODE CONVENTIONS
49+
50+
- All source files must include the Microsoft copyright header.
51+
- All modules must have a module-level docstring.
52+
- Maximum line length is 120 characters.
53+
- Use type annotations on all functions and methods.
54+
55+
---
56+
57+
## CODE FORMATTING
58+
59+
### RUNNING BLACK
60+
61+
**COMMAND:**
62+
```bash
63+
black featuremanagement
64+
```
65+
66+
Line length is configured to 120 in `pyproject.toml`.
67+
68+
**Always run black before pylint and mypy**, as formatting fixes can resolve issues those tools detect.
69+
70+
---
71+
72+
## PYLINT OPERATIONS
73+
74+
### RUNNING PYLINT
75+
76+
**COMMAND:**
77+
```bash
78+
pylint featuremanagement
79+
```
80+
81+
### FIXING PYLINT WARNINGS
82+
83+
**ALLOWED ACTIONS:**
84+
- ✅ Fix warnings with 100% confidence
85+
- ✅ Use existing files for all solutions
86+
- ✅ Reference official guidelines
87+
88+
**FORBIDDEN ACTIONS:**
89+
- ❌ Fix warnings without complete confidence
90+
- ❌ Create new files for solutions
91+
- ❌ Import non-existent modules
92+
- ❌ Add new dependencies/imports
93+
- ❌ Make unnecessary large changes
94+
- ❌ Change code style without reason
95+
- ❌ Delete code without clear justification
96+
97+
---
98+
99+
## MYPY OPERATIONS
100+
101+
### RUNNING MYPY
102+
103+
**COMMAND:**
104+
```bash
105+
mypy featuremanagement
106+
```
107+
108+
The project uses `strict = True` in `mypy.ini`.
109+
110+
---
111+
112+
## TESTING
113+
114+
### RUNNING TESTS
115+
116+
**COMMAND:**
117+
```bash
118+
pytest tests
119+
```
120+
121+
- Sync tests are in `tests/test_*.py`
122+
- Async tests use `pytest-asyncio` and are in files ending with `_async.py`
123+
- Run tests with: `pytest tests`
124+
125+
---
126+
127+
## NEW FEATURES
128+
129+
When adding a new user-facing feature or capability:
130+
131+
- Create a sample in `samples/` demonstrating the feature.
132+
- Add corresponding unit tests (sync and async where applicable).
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
---
2+
name: ci-failure-debugging
3+
description: >
4+
Debug and fix failing CI validation checks for this Python project.
5+
Use when asked to fix CI failures, debug failing PR checks, fix pylint/mypy/black/cspell/pytest errors,
6+
or when a PR validation workflow fails.
7+
---
8+
9+
# CI Failure Debugging
10+
11+
This project's PR validation runs the following checks on Python 3.10–3.14. To debug failures, identify which step failed and follow the corresponding section below.
12+
13+
## Step 1: Identify the failing check
14+
15+
The validation workflow runs these steps in order:
16+
17+
1. **black** — code formatting
18+
2. **pylint** — static analysis
19+
3. **mypy** — type checking (strict mode)
20+
4. **cspell** — spell checking
21+
5. **pytest** — unit tests with coverage
22+
6. **pylint (samples/tests)** — lint samples and tests with relaxed rules
23+
24+
## Step 2: Reproduce locally
25+
26+
Set up the environment first:
27+
28+
```bash
29+
python -m pip install -e ".[dev,test]"
30+
```
31+
32+
Then run the specific failing check:
33+
34+
| Check | Command | Notes |
35+
|-------|---------|-------|
36+
| pylint | `pylint featuremanagement` | |
37+
| black | `black --check featuremanagement` | Use `black featuremanagement` to auto-fix |
38+
| mypy | `mypy featuremanagement` | Uses `strict = True` from `mypy.ini` |
39+
| cspell | `npx cspell "**"` | Config in `cspell.config.yaml`, custom words in `project-words.txt` |
40+
| pytest | `pytest tests --doctest-modules --cov-report=xml --cov-report=html` | |
41+
| pylint (samples) | `pylint --disable=missing-function-docstring,missing-class-docstring samples tests` | Requires `python -m pip install -r samples/requirements.txt` |
42+
43+
## Step 3: Fix the issue
44+
45+
### pylint failures
46+
47+
- Run `pylint featuremanagement` and fix reported issues.
48+
- Do NOT add `# pylint: disable` comments unless absolutely necessary.
49+
- Do NOT add new imports or dependencies to fix warnings.
50+
- The project disables `duplicate-code` in `pyproject.toml`.
51+
- Max line length is 120. Min public methods is 1. Max branches is 20. Max returns is 7.
52+
53+
### black failures
54+
55+
- Run `black featuremanagement` to auto-format. Line length is 120 (configured in `pyproject.toml`).
56+
- If CI uses `black --check`, it means files need reformatting — run `black` locally to fix.
57+
58+
### mypy failures
59+
60+
- Run `mypy featuremanagement`. The project uses `strict = True` with Python 3.10 target.
61+
- All functions must have type annotations.
62+
- Use `Optional[X]` or `X | None` for nullable types.
63+
- Check `mypy.ini` for the full configuration.
64+
65+
### cspell failures
66+
67+
- Misspelled words: fix the typo in your code.
68+
- Legitimate technical terms: add the word to `project-words.txt` (one word per line, alphabetically sorted).
69+
- Do NOT modify `cspell.config.yaml` unless adding a new ignore path.
70+
71+
### pytest failures
72+
73+
- Run `pytest tests` to reproduce.
74+
- Sync tests: `tests/test_*.py`
75+
- Async tests: `tests/test_*_async.py` (use `pytest-asyncio`)
76+
- Time window filter tests: `tests/time_window_filter/`
77+
- Telemetry tests: `tests/test_send_telemetry_appinsights.py`
78+
- If adding new code, ensure both sync and async tests exist where applicable.
79+
80+
### pylint (samples/tests) failures
81+
82+
- This step runs with `--disable=missing-function-docstring,missing-class-docstring`.
83+
- Requires sample dependencies: `python -m pip install -r samples/requirements.txt`.
84+
- Fix any remaining pylint issues in `samples/` and `tests/` directories.

.github/skills/samples/SKILL.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
name: samples
3+
description: >
4+
Guide for creating or updating sample applications in this project.
5+
Use when adding a new sample, modifying an existing sample, or when asked to demonstrate
6+
a feature management capability with example code.
7+
---
8+
9+
# Sample Applications
10+
11+
Samples live in `samples/` and demonstrate feature management capabilities to users.
12+
13+
## File conventions
14+
15+
- Every sample must have the Microsoft copyright header:
16+
```python
17+
# ------------------------------------------------------------------------
18+
# Copyright (c) Microsoft Corporation. All rights reserved.
19+
# Licensed under the MIT License. See License.txt in the project root for
20+
# license information.
21+
# -------------------------------------------------------------------------
22+
```
23+
- Every sample must have a module-level docstring (one-liner describing what it demonstrates).
24+
- Filename should end with `_sample.py` and describe what is being demonstrated (e.g., `feature_flag_sample.py`, `feature_variant_sample_with_telemetry.py`).
25+
26+
## Structure of a sample
27+
28+
Samples follow this general pattern:
29+
30+
```python
31+
# (copyright header)
32+
"""Sample demonstrating <what this shows>."""
33+
34+
import json
35+
import os
36+
import sys
37+
from featuremanagement import FeatureManager, TargetingContext
38+
39+
# Load feature flags from the local JSON file
40+
file_path = os.path.dirname(os.path.abspath(sys.argv[0]))
41+
with open(os.path.join(file_path, "formatted_feature_flags.json"), encoding="utf-8") as f:
42+
feature_flags = json.load(f)
43+
44+
# Create FeatureManager
45+
feature_manager = FeatureManager(feature_flags)
46+
47+
# Demonstrate the feature
48+
result = feature_manager.is_enabled("FlagName")
49+
print(f"FlagName is {'enabled' if result else 'disabled'}")
50+
```
51+
52+
## Feature flag definitions
53+
54+
Sample feature flags go in `formatted_feature_flags.json` under `feature_management.feature_flags`. Each flag needs at minimum `id` and `enabled`. Add filters, variants, allocation, or telemetry as needed for the sample.
55+
56+
## Custom filters
57+
58+
Custom filters used by samples are defined in their own file (e.g., `random_filter.py`) and imported by the samples that need them.
59+
60+
## Async samples
61+
62+
Async samples import from `featuremanagement.aio` instead of `featuremanagement`. See `quarty_sample.py` for the async pattern.
63+
64+
## Azure-connected samples
65+
66+
Samples that connect to Azure App Configuration:
67+
- Use `azure.appconfiguration.provider.load()` to get configuration
68+
- Authenticate using `DefaultAzureCredential` from `azure-identity`, never connection strings
69+
- List Azure dependencies in `samples/requirements.txt`
70+
71+
## Telemetry samples
72+
73+
Two patterns exist:
74+
1. **Callback-based**: Pass `on_feature_evaluated=publish_telemetry` to `FeatureManager` and use `track_event()` from `featuremanagement.azuremonitor`.
75+
2. **Web app span processor**: Use `TargetingSpanProcessor` from `featuremanagement.azuremonitor` with `configure_azure_monitor(span_processors=[...])`.
76+
77+
## Dependencies
78+
79+
Any new package a sample needs must be added to `samples/requirements.txt`. CI installs these before linting samples.
80+
81+
## Linting
82+
83+
Samples are linted with relaxed rules:
84+
```bash
85+
pylint --disable=missing-function-docstring,missing-class-docstring samples tests
86+
```
87+
88+
Function and class docstrings are NOT required in samples, but module-level docstrings ARE.
89+
90+
## Checklist for adding a new sample
91+
92+
1. [ ] Create `samples/feature_<name>_sample.py` with copyright header and module docstring.
93+
2. [ ] Add any new feature flags to `formatted_feature_flags.json`.
94+
3. [ ] Add any new dependencies to `samples/requirements.txt`.
95+
4. [ ] Verify lint passes: `pylint --disable=missing-function-docstring,missing-class-docstring samples`

0 commit comments

Comments
 (0)