Skip to content

feat(hooks): add codereadiness hook - #148

Open
NeaguGeorgiana23 wants to merge 4 commits into
mainfrom
codereadiness_hook
Open

NeaguGeorgiana23 wants to merge 4 commits into
mainfrom
codereadiness_hook

Conversation

@NeaguGeorgiana23

Copy link
Copy Markdown
Contributor

This PR

  • adds the codereadiness hook: an OpenFeature after hook that fails
    a flag evaluation when the running binary's version is lower than the
    minimum version stored in the flag's metadata (default key
    minCodeVersion). On failure the hook throws, so the SDK resolves the
    flag to its default value.
  • adds CodeReadinessHookOptions:
    • strict_validation: when true, missing or malformed version data
      fails the evaluation; when false (the default) it is logged at
      VLOG(1) and the check is skipped. A well-formed current version
      lower than the required one always fails the evaluation.
    • min_version_metadata_key: the metadata key to read the required
      version from.
    • comparator: an optional custom VersionComparator.
  • adds the VersionComparator interface as an extension point for
    non-SemVer version schemes.
  • adds SemVer and SemVerComparator, the default implementation:
    SemVer 2.0.0 precedence with golang.org/x/mod/semver-style parsing
    (optional v prefix, MAJOR and MAJOR.MINOR shorthands). Build
    metadata is validated but ignored.
    • uses one format for every error message:
      codereadiness: flag "<key>": <detail>.
  • adds unit tests for SemVer parsing and precedence, for
    SemVerComparator (including concurrent Compare() calls), and for
    the hook in strict and lenient modes.
  • adds a README with setup, configuration and custom-comparator examples.

Related Issues

Fixes #147

Follow-up Tasks

  • A very similar version of the SemVer lass is already implemented in providers/flagd/src/evaluator/flagd_ops.cpp. Move this to a common folder such that the code can be reused.

How to test

bazel test //hooks/codereadiness/...

Signed-off-by: NeaguGeorgiana23 <neagugeorgiana@google.com>
@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e28fdfba-bb2c-4840-bc3c-e2d2be5a3f05
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Tip

🎯 Customize your risk assessments

Guide how CodeRabbit assesses merge risk and security architecture risk. Highlight sensitive changes and explain your security boundaries using Merge Risk Instructions and Security Risk Instructions in your review settings. Security architecture risk assessments require the Advanced plan or above.

✅ Automatic approvals, with your rules

Let CodeRabbit approve pull requests once required threads are resolved, pre-merge checks pass, and your risk limits are met. Enable Automatic approvals in review settings, with overrides for teams or file paths.

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.

Signed-off-by: NeaguGeorgiana23 <neagugeorgiana@google.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The global -mno-bmi2 flag breaks non-x86 builds, while CI omits the new hook tests and lenient mode still invokes comparison after comparator initialization fails.

3 open issues
What changed in this PR

Adds a configurable OpenFeature code-readiness hook for #147, allowing flag evaluations to fall back to their default value when the application version is below the flag’s required minimum.

Changes:

  • Adds the hook with strict and lenient validation, a configurable metadata key, and custom comparator support.
  • Implements SemVer parsing and comparison, with unit tests and usage documentation.
  • Adds Bazel library/test targets and compiler workarounds.
File Description
hooks/​codereadiness/​tests/​semver_test.cpp Tests parsing and version precedence.
hooks/​codereadiness/​tests/​semver_comparator_test.cpp Tests comparator initialization, results, and concurrent calls.
hooks/​codereadiness/​tests/​codereadiness_test.cpp Tests validation modes, metadata, and custom comparators.
hooks/​codereadiness/​tests/​BUILD Defines three test targets.
hooks/​codereadiness/​src/​version_comparator.h Defines the custom comparator interface.
hooks/​codereadiness/​src/​semver.h Declares the semantic-version model.
hooks/​codereadiness/​src/​semver.cpp Implements parsing and precedence rules.
hooks/​codereadiness/​src/​semver_comparator.h Declares the default comparator.
hooks/​codereadiness/​src/​semver_comparator.cpp Implements minimum-version comparisons.
hooks/​codereadiness/​src/​codereadiness.h Defines hook options and public API.
hooks/​codereadiness/​src/​codereadiness.cpp Implements metadata validation and evaluation failures.
hooks/​codereadiness/​src/​BUILD Defines public library targets.
hooks/​codereadiness/​README.md Documents setup, behavior, and customization.
hooks/​codereadiness/​LICENSE Adds the Apache 2.0 license.
.bazelrc Adds BoringSSL warning and BMI2 compiler workarounds.

Review effort: Balanced

Comment thread .bazelrc Outdated
Comment on lines +14 to +15
build --copt=-mno-bmi2
build --host_copt=-mno-bmi2

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@m-olko wdyt about this comment? I added the workaround because build was failing without it.

@m-olko m-olko Nov 3, 2026 •

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.

Have you tried updating bazel to 20260817.0? I have seen some threads about similar issues and theoretically they have been fixed with newer versions

Other question is why abseil is not updated automatically by renovate

Comment on lines +45 to +47
VLOG(1) << "codereadiness: invalid current version \"" << current_version
<< "\": " << status;
}
load("@rules_cc//cc:defs.bzl", "cc_test")

cc_test(
name = "semver_test",
Signed-off-by: NeaguGeorgiana23 <neagugeorgiana@google.com>
@m-olko

m-olko commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

The current version of cpp-sdk doesn't have HookLifecycle implemented, from what I have seen, that's why you need to create manual RunAfter function in your tests. Could you first create new release on cpp-sdk with Hooks fully implemented, and then test the hook in e2e fashion, using openfeature provider?

Signed-off-by: NeaguGeorgiana23 <neagugeorgiana@google.com>
Comment thread .bazelrc Resolved
Comment on lines +37 to +47
if (absl::Status status = comparator->Initialize(current_version);
!status.ok()) {
if (options.strict_validation) {
return absl::Status(
status.code(),
absl::StrCat("codereadiness: comparator initialization failed: ",
status.message()));
}
VLOG(1) << "codereadiness: invalid current version \"" << current_version
<< "\": " << status;
}

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.

Inability to initialize the comparator should fail Create() in all modes, not only when strict_validation is enabled. An invalid current_version at startup means the hook is misconfigured, so we should surface that error to the caller immediately rather than creating a broken hook that never validates anything.

Failing Create() unconditionally when comparator->Initialize(current_version) returns a non-OK status also means Compare() is only ever called on a successfully initialized comparator, which simplifies SemVerComparator (no need to track current_version_ or std::optional<SemVer> for uninitialized state) and custom VersionComparator implementations.

Comment on lines +98 to +116
current_version_, "\" - minimum: \"",
*min_code_version, "\" for flag \"", flag_key,
"\": ", meets_min_version.status().message()));
return;
}
if (!*meets_min_version) {
throw std::runtime_error(
absl::StrCat("current version: \"", current_version_,
"\" required minimum version: \"", *min_code_version,
"\" flag \"", flag_key, "\", check failed"));
}
}

void CodeReadinessHook::FailOrSkip(const std::string& message) const {
if (strict_validation_) {
throw std::runtime_error(message);
}
VLOG(1) << "codereadiness: " << message << ", skipping validation";
}

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.

The PR description notes that error messages follow the format codereadiness: flag "<key>": <detail>, and Create() prefixes statuses with codereadiness: , but After() and FailOrSkip() only include the codereadiness: prefix in the VLOG(1) output and omit it from the thrown std::runtime_error messages.

Could we align the thrown exception messages with the documented format (or update the PR description if the Go hook's message format is intentional here)?

load("@rules_cc//cc:defs.bzl", "cc_test")

cc_test(
name = "semver_test",

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.

+1 to updating .github/workflows/ci-format-test-lint.yml so the test step runs bazel test //... (or includes //hooks/...), and updating HeaderFilterRegex in .clang-tidy from ".*/flagd/.*" to ".*/(flagd|hooks)/.*" so headers under hooks/ are also checked by clang-tidy.

namespace codereadiness {

// Represents a Semantic Version (SemVer 2.0.0) for comparison.
// Parsing follows golang.org/x/mod/semver: optional leading 'v'/'V', MAJOR and

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.

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.

Create CodeReadiness Hook

4 participants