-
Notifications
You must be signed in to change notification settings - Fork 7
Adding Copilot Skills #65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| --- | ||
| name: ci-failure-debugging | ||
| description: > | ||
| Debug and fix failing CI validation checks for this Python project. | ||
| Use when asked to fix CI failures, debug failing PR checks, fix pylint/mypy/black/cspell/pytest errors, | ||
| or when a PR validation workflow fails. | ||
| --- | ||
|
|
||
| # CI Failure Debugging | ||
|
|
||
| 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. | ||
|
|
||
| ## Step 1: Identify the failing check | ||
|
|
||
| The validation workflow runs these steps in order: | ||
|
|
||
| 1. **black** — code formatting | ||
| 2. **pylint** — static analysis | ||
| 3. **mypy** — type checking (strict mode) | ||
| 4. **cspell** — spell checking | ||
| 5. **pytest** — unit tests with coverage | ||
| 6. **pylint (samples/tests)** — lint samples and tests with relaxed rules | ||
|
|
||
| ## Step 2: Reproduce locally | ||
|
|
||
| Set up the environment first: | ||
|
|
||
| ```bash | ||
| python -m pip install -e ".[dev,test]" | ||
| ``` | ||
|
|
||
| Then run the specific failing check: | ||
|
|
||
| | Check | Command | Notes | | ||
| |-------|---------|-------| | ||
| | pylint | `pylint featuremanagement` | | | ||
| | black | `black --check featuremanagement` | Use `black featuremanagement` to auto-fix | | ||
| | mypy | `mypy featuremanagement` | Uses `strict = True` from `mypy.ini` | | ||
| | cspell | `npx cspell "**"` | Config in `cspell.config.yaml`, custom words in `project-words.txt` | | ||
| | pytest | `pytest tests --doctest-modules --cov-report=xml --cov-report=html` | | | ||
| | pylint (samples) | `pylint --disable=missing-function-docstring,missing-class-docstring samples tests` | Requires `python -m pip install -r samples/requirements.txt` | | ||
|
|
||
| ## Step 3: Fix the issue | ||
|
|
||
| ### pylint failures | ||
|
|
||
| - Run `pylint featuremanagement` and fix reported issues. | ||
| - Do NOT add `# pylint: disable` comments unless absolutely necessary. | ||
| - Do NOT add new imports or dependencies to fix warnings. | ||
| - The project disables `duplicate-code` in `pyproject.toml`. | ||
| - Max line length is 120. Min public methods is 1. Max branches is 20. Max returns is 7. | ||
|
|
||
| ### black failures | ||
|
|
||
| - Run `black featuremanagement` to auto-format. Line length is 120 (configured in `pyproject.toml`). | ||
| - If CI uses `black --check`, it means files need reformatting — run `black` locally to fix. | ||
|
|
||
| ### mypy failures | ||
|
|
||
| - Run `mypy featuremanagement`. The project uses `strict = True` with Python 3.10 target. | ||
| - All functions must have type annotations. | ||
| - Use `Optional[X]` or `X | None` for nullable types. | ||
| - Check `mypy.ini` for the full configuration. | ||
|
|
||
| ### cspell failures | ||
|
|
||
| - Misspelled words: fix the typo in your code. | ||
| - Legitimate technical terms: add the word to `project-words.txt` (one word per line, alphabetically sorted). | ||
| - Do NOT modify `cspell.config.yaml` unless adding a new ignore path. | ||
|
|
||
| ### pytest failures | ||
|
|
||
| - Run `pytest tests` to reproduce. | ||
| - Sync tests: `tests/test_*.py` | ||
| - Async tests: `tests/test_*_async.py` (use `pytest-asyncio`) | ||
| - Time window filter tests: `tests/time_window_filter/` | ||
| - Telemetry tests: `tests/test_send_telemetry_appinsights.py` | ||
| - If adding new code, ensure both sync and async tests exist where applicable. | ||
|
|
||
| ### pylint (samples/tests) failures | ||
|
|
||
| - This step runs with `--disable=missing-function-docstring,missing-class-docstring`. | ||
| - Requires sample dependencies: `python -m pip install -r samples/requirements.txt`. | ||
| - Fix any remaining pylint issues in `samples/` and `tests/` directories. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| --- | ||
| name: samples | ||
| description: > | ||
| Guide for creating or updating sample applications in this project. | ||
| Use when adding a new sample, modifying an existing sample, or when asked to demonstrate | ||
| a feature management capability with example code. | ||
| --- | ||
|
|
||
| # Sample Applications | ||
|
|
||
| Samples live in `samples/` and demonstrate feature management capabilities to users. | ||
|
|
||
| ## File conventions | ||
|
|
||
| - Every sample must have the Microsoft copyright header: | ||
| ```python | ||
| # ------------------------------------------------------------------------ | ||
| # Copyright (c) Microsoft Corporation. All rights reserved. | ||
| # Licensed under the MIT License. See License.txt in the project root for | ||
| # license information. | ||
| # ------------------------------------------------------------------------- | ||
| ``` | ||
| - Every sample must have a module-level docstring (one-liner describing what it demonstrates). | ||
| - Filename should end with `_sample.py` and describe what is being demonstrated (e.g., `feature_flag_sample.py`, `feature_variant_sample_with_telemetry.py`). | ||
|
|
||
| ## Structure of a sample | ||
|
|
||
| Samples follow this general pattern: | ||
|
|
||
| ```python | ||
| # (copyright header) | ||
| """Sample demonstrating <what this shows>.""" | ||
|
|
||
| import json | ||
| import os | ||
| import sys | ||
| from featuremanagement import FeatureManager, TargetingContext | ||
|
|
||
| # Load feature flags from the local JSON file | ||
| file_path = os.path.dirname(os.path.abspath(sys.argv[0])) | ||
| with open(os.path.join(file_path, "formatted_feature_flags.json"), encoding="utf-8") as f: | ||
| feature_flags = json.load(f) | ||
|
|
||
| # Create FeatureManager | ||
| feature_manager = FeatureManager(feature_flags) | ||
|
|
||
| # Demonstrate the feature | ||
| result = feature_manager.is_enabled("FlagName") | ||
| print(f"FlagName is {'enabled' if result else 'disabled'}") | ||
| ``` | ||
|
|
||
| ## Feature flag definitions | ||
|
|
||
| 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. | ||
|
|
||
| ## Custom filters | ||
|
|
||
| Custom filters used by samples are defined in their own file (e.g., `random_filter.py`) and imported by the samples that need them. | ||
|
|
||
| ## Async samples | ||
|
|
||
| Async samples import from `featuremanagement.aio` instead of `featuremanagement`. See `quarty_sample.py` for the async pattern. | ||
|
|
||
| ## Azure-connected samples | ||
|
|
||
| Samples that connect to Azure App Configuration: | ||
| - Use `azure.appconfiguration.provider.load()` to get configuration | ||
| - Authenticate using `DefaultAzureCredential` from `azure-identity`, never connection strings | ||
| - List Azure dependencies in `samples/requirements.txt` | ||
|
|
||
| ## Telemetry samples | ||
|
|
||
| Two patterns exist: | ||
| 1. **Callback-based**: Pass `on_feature_evaluated=publish_telemetry` to `FeatureManager` and use `track_event()` from `featuremanagement.azuremonitor`. | ||
| 2. **Web app span processor**: Use `TargetingSpanProcessor` from `featuremanagement.azuremonitor` with `configure_azure_monitor(span_processors=[...])`. | ||
|
|
||
| ## Dependencies | ||
|
|
||
| Any new package a sample needs must be added to `samples/requirements.txt`. CI installs these before linting samples. | ||
|
|
||
| ## Linting | ||
|
|
||
| Samples are linted with relaxed rules: | ||
| ```bash | ||
| pylint --disable=missing-function-docstring,missing-class-docstring samples tests | ||
| ``` | ||
|
|
||
| Function and class docstrings are NOT required in samples, but module-level docstrings ARE. | ||
|
|
||
| ## Checklist for adding a new sample | ||
|
|
||
| 1. [ ] Create `samples/feature_<name>_sample.py` with copyright header and module docstring. | ||
| 2. [ ] Add any new feature flags to `formatted_feature_flags.json`. | ||
| 3. [ ] Add any new dependencies to `samples/requirements.txt`. | ||
| 4. [ ] Verify lint passes: `pylint --disable=missing-function-docstring,missing-class-docstring samples` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| --- | ||
| name: sync-async-pattern | ||
| description: > | ||
| Guide for implementing sync/async mirrored code in this project. | ||
| Use when adding new classes, methods, or feature filters that need both sync and async versions, | ||
| or when modifying existing sync code that has an async counterpart in featuremanagement/aio/. | ||
| --- | ||
|
|
||
| # Sync/Async Mirroring Pattern | ||
|
|
||
| This project maintains parallel sync and async implementations. Every change to sync code in `featuremanagement/` must be mirrored in `featuremanagement/aio/`, and vice versa. | ||
|
|
||
| ## Directory mapping | ||
|
|
||
| | Sync | Async | | ||
| |------|-------| | ||
| | `featuremanagement/_featuremanager.py` | `featuremanagement/aio/_featuremanager.py` | | ||
| | `featuremanagement/_featurefilters.py` | `featuremanagement/aio/_featurefilters.py` | | ||
| | `featuremanagement/_defaultfilters.py` | `featuremanagement/aio/_defaultfilters.py` | | ||
| | `featuremanagement/__init__.py` | `featuremanagement/aio/__init__.py` | | ||
|
|
||
| Shared code that does NOT have an async counterpart: | ||
| - `featuremanagement/_featuremanagerbase.py` — base class used by both sync and async `FeatureManager` | ||
| - `featuremanagement/_models/` — data models imported by both | ||
| - `featuremanagement/_time_window_filter/` — time window logic (no I/O, used as-is) | ||
| - `featuremanagement/azuremonitor/` — telemetry (no async version) | ||
|
|
||
| ## Copyright header | ||
|
|
||
| Every source file MUST start with: | ||
|
|
||
| ```python | ||
| # ------------------------------------------------------------------------ | ||
| # Copyright (c) Microsoft Corporation. All rights reserved. | ||
| # Licensed under the MIT License. See License.txt in the project root for | ||
| # license information. | ||
| # ------------------------------------------------------------------------- | ||
| ``` | ||
|
|
||
| Followed by a module-level docstring. | ||
|
|
||
| ## How to convert sync to async | ||
|
|
||
| ### Classes | ||
|
|
||
| - Keep the **same class name** (e.g., both are `FeatureManager`). Users disambiguate by import path. | ||
| - Both sync and async `FeatureManager` inherit from `FeatureManagerBase`. | ||
|
|
||
| ### Methods | ||
|
|
||
| - Add `async` to method definitions: `def evaluate(...)` → `async def evaluate(...)` | ||
| - Add `await` to calls that invoke filters, callbacks, or accessors. | ||
|
|
||
| ### Default filters (composition pattern) | ||
|
|
||
| Async default filters do NOT duplicate logic. They wrap the sync implementation: | ||
|
|
||
| ```python | ||
| from .._defaultfilters import TimeWindowFilter as SyncTimeWindowFilter | ||
|
|
||
| class TimeWindowFilter(FeatureFilter): | ||
| def __init__(self): | ||
| self._filter = SyncTimeWindowFilter() | ||
|
|
||
| @FeatureFilter.alias("Microsoft.TimeWindow") | ||
| async def evaluate(self, context, **kwargs): | ||
| return self._filter.evaluate(context, **kwargs) | ||
| ``` | ||
|
|
||
| Use this pattern for any new filter whose `evaluate` does not perform I/O. | ||
|
|
||
| ### Callbacks and accessors | ||
|
|
||
| The async `FeatureManager` supports BOTH sync and async callbacks. Use `inspect.iscoroutinefunction` to detect and handle both: | ||
|
|
||
| ```python | ||
| import inspect | ||
|
|
||
| if inspect.iscoroutinefunction(self._on_feature_evaluated): | ||
| await self._on_feature_evaluated(result) | ||
| else: | ||
| self._on_feature_evaluated(result) | ||
| ``` | ||
|
|
||
| ### Imports | ||
|
|
||
| - Sync files import from `._models`, `._featurefilters`, etc. | ||
| - Async files import from `.._models`, `.._featurefilters`, etc. (one level up from `aio/`). | ||
|
|
||
| ## `__init__.py` exports | ||
|
|
||
| ### Sync (`featuremanagement/__init__.py`) | ||
|
|
||
| Exports everything: `FeatureManager`, filters, all models, `__version__`, and defines `__all__`. | ||
|
|
||
| ### Async (`featuremanagement/aio/__init__.py`) | ||
|
|
||
| Exports ONLY async-specific classes: `FeatureManager`, `FeatureFilter`, `TimeWindowFilter`, `TargetingFilter`. Does NOT re-export models or `__version__` — users import those from the sync package. | ||
|
|
||
| When adding a new public class: | ||
| 1. Add to sync `__init__.py` with `__all__` entry. | ||
| 2. If it has an async version, add to async `__init__.py` with `__all__` entry. | ||
|
|
||
| ## Test file naming | ||
|
|
||
| | Sync test | Async counterpart | | ||
| |-----------|-------------------| | ||
| | `tests/test_feature_manager.py` | `tests/test_feature_manager_async.py` | | ||
| | `tests/test_feature_variants.py` | `tests/test_feature_variants_async.py` | | ||
| | `tests/test_default_feature_flags.py` | `tests/test_default_feature_flags_async.py` | | ||
|
|
||
| - Async test files append `_async` to the sync filename. | ||
| - Async tests use `pytest-asyncio` with `@pytest.mark.asyncio` on test functions. | ||
| - Not every sync test needs an async counterpart (e.g., refresh and telemetry tests are sync-only). | ||
|
|
||
| ## Checklist for adding new code | ||
|
|
||
| 1. [ ] Write the sync implementation in `featuremanagement/`. | ||
| 2. [ ] Write the async mirror in `featuremanagement/aio/` following the patterns above. | ||
| 3. [ ] Export from both `__init__.py` files if public. | ||
| 4. [ ] Write sync tests in `tests/test_*.py`. | ||
| 5. [ ] Write async tests in `tests/test_*_async.py`. | ||
| 6. [ ] Run all validation: `pylint featuremanagement`, `black featuremanagement`, `mypy featuremanagement`, `pytest tests`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.