Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into feat/grpc-sync-addi…
Browse files Browse the repository at this point in the history
…tion

Signed-off-by: Simon Schrottner <[email protected]>
  • Loading branch information
aepfli committed Dec 29, 2024
2 parents a37e5a3 + 9dcb6a5 commit 4db7a48
Show file tree
Hide file tree
Showing 25 changed files with 406 additions and 199 deletions.
18 changes: 9 additions & 9 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ jobs:
- "providers/openfeature-provider-ofrep"

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
submodules: recursive

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
Expand All @@ -60,7 +60,7 @@ jobs:

- if: matrix.python-version == '3.11'
name: Upload coverage to Codecov
uses: codecov/codecov-action@v4.5.0
uses: codecov/codecov-action@1e68e06f1dbfde0e4cefc87efeba9e4643565303 # v5.1.2
with:
name: Code Coverage for ${{ matrix.package }} on Python ${{ matrix.python-version }}
directory: ${{ matrix.package }}
Expand All @@ -72,14 +72,14 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5
with:
python-version: "3.11"
cache: "pip"

- name: Run pre-commit
uses: pre-commit/[email protected]
uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1

sast:
runs-on: ubuntu-latest
Expand All @@ -88,13 +88,13 @@ jobs:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3
with:
languages: python
config-file: ./.github/codeql-config.yml

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3
6 changes: 3 additions & 3 deletions .github/workflows/lint-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ jobs:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v5
- uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5
id: lint_pr_title
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- uses: marocchino/sticky-pull-request-comment@v2
- uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2
# When the previous steps fails, the workflow would stop. By adding this
# condition you can continue the execution with the populated error message.
if: always() && (steps.lint_pr_title.outputs.error_message != null)
Expand All @@ -44,7 +44,7 @@ jobs:
# Delete a previous comment when the issue has been resolved
- if: ${{ steps.lint_pr_title.outputs.error_message == null }}
uses: marocchino/sticky-pull-request-comment@v2
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2
with:
header: pr-title-lint-error
delete: true
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
pull-requests: write # for googleapis/release-please-action to create release PR
# Release-please creates a PR that tracks all changes
steps:
- uses: googleapis/release-please-action@v4
- uses: googleapis/release-please-action@7987652d64b4581673a76e33ad5e98e3dd56832f # v4
id: release
with:
token: ${{secrets.GITHUB_TOKEN}}
Expand All @@ -46,10 +46,10 @@ jobs:
# IMPORTANT: this permission is mandatory for trusted publishing to pypi
id-token: write
container:
image: "python:3.12"
image: "python:3.13"

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
submodules: recursive

Expand Down
1 change: 1 addition & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[submodule "providers/openfeature-provider-flagd/test-harness"]
path = providers/openfeature-provider-flagd/openfeature/test-harness
url = [email protected]:open-feature/flagd-testbed.git
branch = v0.5.18
[submodule "providers/openfeature-provider-flagd/spec"]
path = providers/openfeature-provider-flagd/openfeature/spec
url = https://github.com/open-feature/spec
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
default_stages: [commit]
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.3
rev: v0.8.4
hooks:
- id: ruff
args: [--fix]
- id: ruff-format

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v5.0.0
hooks:
- id: check-toml
- id: check-yaml
Expand Down
24 changes: 12 additions & 12 deletions providers/openfeature-provider-flagd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,12 @@ This mode is useful for local development, tests and offline applications.
The default options can be defined in the FlagdProvider constructor.

| Option name | Environment variable name | Type & Values | Default | Compatible resolver |
| ------------------------ | ------------------------------ | -------------------------- | ----------------------------- | ------------------- |
|--------------------------|--------------------------------|----------------------------|-------------------------------|---------------------|
| resolver_type | FLAGD_RESOLVER | enum - `rpc`, `in-process` | rpc | |
| host | FLAGD_HOST | str | localhost | rpc & in-process |
| port | FLAGD_PORT | int | 8013 (rpc), 8015 (in-process) | rpc & in-process |
| tls | FLAGD_TLS | bool | false | rpc & in-process |
| cert_path | FLAGD_SERVER_CERT_PATH | String | null | rpc & in-process |
| deadline | FLAGD_DEADLINE_MS | int | 500 | rpc & in-process |
| stream_deadline_ms | FLAGD_STREAM_DEADLINE_MS | int | 600000 | rpc & in-process |
| keep_alive_time | FLAGD_KEEP_ALIVE_TIME_MS | int | 0 | rpc & in-process |
Expand All @@ -96,8 +97,6 @@ The default options can be defined in the FlagdProvider constructor.
<!-- not implemented
| target_uri | FLAGD_TARGET_URI | alternative to host/port, supporting custom name resolution | string | null | rpc & in-process |
| socket_path | FLAGD_SOCKET_PATH | alternative to host port, unix socket | String | null | rpc & in-process |
| cert_path | FLAGD_SERVER_CERT_PATH | tls cert path | String | null | rpc & in-process |
| max_event_stream_retries | FLAGD_MAX_EVENT_STREAM_RETRIES | int | 5 | rpc |
| context_enricher | - | sync-metadata to evaluation context mapping function | function | identity function | in-process |
| offline_pollIntervalMs | FLAGD_OFFLINE_POLL_MS | poll interval for reading offlineFlagSourcePath | int | 5000 | in-process |
-->
Expand Down Expand Up @@ -132,17 +131,18 @@ and the evaluation will default.

TLS is available in situations where flagd is running on another host.

<!--

You may optionally supply an X.509 certificate in PEM format. Otherwise, the default certificate store will be used.
```java
FlagdProvider flagdProvider = new FlagdProvider(
FlagdOptions.builder()
.host("myflagdhost")
.tls(true) // use TLS
.certPath("etc/cert/ca.crt") // PEM cert
.build());

```python
from openfeature import api
from openfeature.contrib.provider.flagd import FlagdProvider

api.set_provider(FlagdProvider(
tls=True, # use TLS
cert_path="etc/cert/ca.crt" # PEM cert
))
```
-->

## License

Expand Down
2 changes: 1 addition & 1 deletion providers/openfeature-provider-flagd/openfeature/schemas
2 changes: 1 addition & 1 deletion providers/openfeature-provider-flagd/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ dependencies = [
"pytest-bdd",
"testcontainers",
"asserts",
"grpcio-health-checking==1.60.0",
"grpcio-health-checking==1.68.1",
]
pre-install-commands = [
"hatch build",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ class CacheType(Enum):
DEFAULT_RESOLVER_TYPE = ResolverType.RPC
DEFAULT_RETRY_BACKOFF = 1000
DEFAULT_RETRY_BACKOFF_MAX = 120000
DEFAULT_RETRY_GRACE_ATTEMPTS = 5
DEFAULT_RETRY_GRACE_PERIOD_SECONDS = 5
DEFAULT_STREAM_DEADLINE = 600000
DEFAULT_TLS = False
DEFAULT_TLS_CERT: typing.Optional[str] = None

ENV_VAR_CACHE_SIZE = "FLAGD_MAX_CACHE_SIZE"
ENV_VAR_CACHE_TYPE = "FLAGD_CACHE"
Expand All @@ -41,10 +42,11 @@ class CacheType(Enum):
ENV_VAR_RESOLVER_TYPE = "FLAGD_RESOLVER"
ENV_VAR_RETRY_BACKOFF_MS = "FLAGD_RETRY_BACKOFF_MS"
ENV_VAR_RETRY_BACKOFF_MAX_MS = "FLAGD_RETRY_BACKOFF_MAX_MS"
ENV_VAR_RETRY_GRACE_ATTEMPTS = "FLAGD_RETRY_GRACE_ATTEMPTS"
ENV_VAR_SELECTOR = "FLAGD_SELECTOR"
ENV_VAR_RETRY_GRACE_PERIOD_SECONDS = "FLAGD_RETRY_GRACE_PERIOD"
ENV_VAR_SELECTOR = "FLAGD_SOURCE_SELECTOR"
ENV_VAR_STREAM_DEADLINE_MS = "FLAGD_STREAM_DEADLINE_MS"
ENV_VAR_TLS = "FLAGD_TLS"
ENV_VAR_TLS_CERT = "FLAGD_SERVER_CERT_PATH"

T = typing.TypeVar("T")

Expand Down Expand Up @@ -83,12 +85,13 @@ def __init__( # noqa: PLR0913
offline_poll_interval_ms: typing.Optional[int] = None,
retry_backoff_ms: typing.Optional[int] = None,
retry_backoff_max_ms: typing.Optional[int] = None,
retry_grace_attempts: typing.Optional[int] = None,
retry_grace_period: typing.Optional[int] = None,
deadline_ms: typing.Optional[int] = None,
stream_deadline_ms: typing.Optional[int] = None,
keep_alive_time: typing.Optional[int] = None,
cache: typing.Optional[CacheType] = None,
max_cache_size: typing.Optional[int] = None,
cert_path: typing.Optional[str] = None,
):
self.host = env_or_default(ENV_VAR_HOST, DEFAULT_HOST) if host is None else host

Expand Down Expand Up @@ -117,14 +120,16 @@ def __init__( # noqa: PLR0913
else retry_backoff_max_ms
)

self.retry_grace_attempts: int = (
self.retry_grace_period: int = (
int(
env_or_default(
ENV_VAR_RETRY_GRACE_ATTEMPTS, DEFAULT_RETRY_GRACE_ATTEMPTS, cast=int
ENV_VAR_RETRY_GRACE_PERIOD_SECONDS,
DEFAULT_RETRY_GRACE_PERIOD_SECONDS,
cast=int,
)
)
if retry_grace_attempts is None
else retry_grace_attempts
if retry_grace_period is None
else retry_grace_period
)

self.resolver = (
Expand Down Expand Up @@ -201,6 +206,12 @@ def __init__( # noqa: PLR0913
else max_cache_size
)

self.cert_path = (
env_or_default(ENV_VAR_TLS_CERT, DEFAULT_TLS_CERT)
if cert_path is None
else cert_path
)

self.selector = (
env_or_default(ENV_VAR_SELECTOR, None) if selector is None else selector
)
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import warnings

from openfeature.evaluation_context import EvaluationContext
from openfeature.event import ProviderEventDetails
from openfeature.flag_evaluation import FlagResolutionDetails
from openfeature.provider.metadata import Metadata
from openfeature.provider.provider import AbstractProvider
Expand Down Expand Up @@ -55,7 +54,8 @@ def __init__( # noqa: PLR0913
cache_type: typing.Optional[CacheType] = None,
max_cache_size: typing.Optional[int] = None,
retry_backoff_max_ms: typing.Optional[int] = None,
retry_grace_attempts: typing.Optional[int] = None,
retry_grace_period: typing.Optional[int] = None,
cert_path: typing.Optional[str] = None,
):
"""
Create an instance of the FlagdProvider
Expand Down Expand Up @@ -86,14 +86,15 @@ def __init__( # noqa: PLR0913
deadline_ms=deadline,
retry_backoff_ms=retry_backoff_ms,
retry_backoff_max_ms=retry_backoff_max_ms,
retry_grace_attempts=retry_grace_attempts,
retry_grace_period=retry_grace_period,
selector=selector,
resolver=resolver_type,
offline_flag_source_path=offline_flag_source_path,
cache=cache_type,
max_cache_size=max_cache_size,
stream_deadline_ms=stream_deadline_ms,
keep_alive_time=keep_alive_time,
cache=cache_type,
max_cache_size=max_cache_size,
cert_path=cert_path,
)

self.resolver = self.setup_resolver()
Expand All @@ -112,6 +113,7 @@ def setup_resolver(self) -> AbstractResolver:
self.config,
self.emit_provider_ready,
self.emit_provider_error,
self.emit_provider_stale,
self.emit_provider_configuration_changed,
)
else:
Expand All @@ -130,11 +132,6 @@ def get_metadata(self) -> Metadata:
"""Returns provider metadata"""
return Metadata(name="FlagdProvider")

def flag_store_updated_callback(self, flag_keys: typing.List[str]) -> None:
self.emit_provider_configuration_changed(
ProviderEventDetails(flags_changed=flag_keys)
)

def resolve_boolean_details(
self,
key: str,
Expand Down
Loading

0 comments on commit 4db7a48

Please sign in to comment.