Skip to content

test: add 26 tests and clean up stale docs#27

Merged
yairfalse merged 2 commits into
mainfrom
feature/update-sykli
Feb 20, 2026
Merged

test: add 26 tests and clean up stale docs#27
yairfalse merged 2 commits into
mainfrom
feature/update-sykli

Conversation

@yairfalse
Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #26 (merged). Addresses test coverage gaps and doc cleanup:

  • 26 new tests (268 → 294): evaluate_ab_experiment (10), CDEvents A/B (2), prometheus_ab edge cases (5), query builders (2), traffic/validation/status/occurrence (7)
  • Enhanced MockPrometheusClient with response queue for multi-query test scenarios
  • Deleted stale docs: 4 ADRs (unimplemented vision), PLAN.md, CODE_REVIEW.md
  • Updated CLAUDE.md: new module structure, file locations, features, 294+ tests
  • Updated README.md: A/B Testing → Yes, FALSE Protocol feature, 294+ badge, Rust 1.85+
  • CI fix: Rust Docker image 1.83 → 1.85 for edition 2024 (kube 2.0.1)

Test plan

  • 294 tests passing (cargo test)
  • cargo clippy -- -D warnings clean
  • cargo fmt clean

🤖 Generated with Claude Code

yairfalse and others added 2 commits February 21, 2026 00:00
- 10 evaluate_ab_experiment tests (manual conclude, max/min duration,
  insufficient samples, Prometheus failures, statistical significance)
- 2 CDEvents A/B tests (experiment concluded, A/B initialization)
- 5 prometheus_ab edge cases (empty results, zero rates, se=0, consensus A)
- 2 Prometheus AB query builder tests
- 2 default_service_port tests
- 1 validation negative deadline test
- 2 status tests (A/B initialization, invalid timestamp)
- 3 occurrence tests (missing namespace, Initializing/Experimenting suffixes)
- Enhanced MockPrometheusClient with response queue for multi-query tests

Test count: 268 → 294

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Delete stale/aspirational documents:
- docs/adr/001-004 (unimplemented vision docs)
- docs/PLAN.md (outdated roadmap)
- docs/CODE_REVIEW.md (stale line references)

Update CLAUDE.md:
- Architecture diagram with new module structure
- A/B testing, FALSE Protocol, clock in feature list
- File locations table with all new files
- Test count 294+, ulid dependency

Update README.md:
- A/B Testing: Planned → Yes
- Added FALSE Protocol feature
- Test badge 294+, Rust 1.85+ requirement

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@yairfalse yairfalse force-pushed the feature/update-sykli branch from 1570277 to e0163d4 Compare February 20, 2026 23:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds A/B testing support and expands controller/test infrastructure while cleaning up documentation and updating CI/tooling for the newer Rust toolchain.

Changes:

  • Introduces A/B testing strategy (CRD types, controller strategy, Prometheus-based significance evaluation) plus supporting status/traffic/replicaset utilities.
  • Refactors controller dependencies via traits (EventSink, MetricsQuerier, Clock) and adds FALSE Protocol occurrence emission.
  • Expands test coverage and updates CRD/README/CI to reflect new features and Rust 1.85+.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/stress_test.rs Updates Rollout test builders for new strategy fields (ab_testing, port).
tests/seppo_integration_test.rs Updates integration tests for new strategy fields (ab_testing, port).
sykli.rs Bumps Rust container image used by the Sykli pipeline to 1.85.
src/main.rs Switches to new HTTP-based sinks/clients and injects Clock into controller Context.
src/crd/rollout_test.rs Adds serialization/deserialization tests for A/B strategy and new phases/status fields.
src/crd/rollout.rs Extends CRD Rust types with A/B strategy, ports, new phases, and A/B experiment status structs.
src/crd/conversion_test.rs Updates conversion tests to account for new strategy/port fields.
src/controller/strategies/simple.rs Updates strategy trait signature and status fields to include clock “now” and ab_experiment.
src/controller/strategies/mod.rs Adds A/B strategy module and updates RolloutStrategy trait to accept now.
src/controller/strategies/canary.rs Wires now through status computation and updates tests for new fields.
src/controller/strategies/blue_green.rs Updates trait signature to accept now and updates tests for new fields.
src/controller/strategies/ab_testing.rs New A/B strategy implementation: ReplicaSets + HTTPRoute rules + status progression.
src/controller/rollout/validation.rs New runtime validation + duration parsing helpers used by reconcile/webhook paths.
src/controller/rollout/traffic.rs New traffic helpers (ports + backend refs/weights + HTTPRoute mutation utilities).
src/controller/rollout/status.rs New status state-machine helpers (init/progress/pause/requeue/deadline checks).
src/controller/rollout/replicaset.rs New ReplicaSet builders, surge parsing, and pod-template hashing.
src/controller/rollout/reconcile.rs New main reconcile loop using the split rollout modules, metrics evaluation, and A/B evaluation.
src/controller/prometheus_ab.rs New Z-test based statistical analysis utilities for A/B experiment conclusions.
src/controller/prometheus.rs Introduces MetricsQuerier trait, HttpPrometheusClient, and queued-response mock client.
src/controller/occurrence.rs New FALSE Protocol occurrence emission (file writer + mapping from phases/strategies).
src/controller/mod.rs Registers new controller submodules (clock/occurrence/prometheus_ab).
src/controller/clock.rs New Clock abstraction (SystemClock + MockClock).
src/controller/cdevents_test.rs Updates tests to use the new EventSink trait + adds A/B concluded/deployed event coverage.
src/controller/cdevents.rs Refactors to EventSink trait with HTTP and mock implementations; adds experiment conclusion event data.
deploy/crd.yaml Regenerates CRD schema with A/B strategy + ports + new status fields/phases.
README.md Updates feature matrix and counts (tests, Rust version, A/B testing, FALSE Protocol).
Cargo.toml Adds ulid dependency for FALSE Protocol occurrence IDs.
Cargo.lock Locks ulid and transitive dependencies.
CLAUDE.md Updates repo/module structure docs and feature list/test counts.
.github/workflows/sykli-ci.yml Reworks CI workflow and installs/runs Sykli.
Comments suppressed due to low confidence (2)

src/controller/occurrence.rs:169

  • build_occurrence_type maps strategy names using underscore variants (e.g. "blue_green", "ab_testing"), but the actual strategy names returned by handlers are hyphenated (e.g. "blue-green", "ab-testing"). This will produce unexpected FALSE Protocol types like blue-green.rollout.completed instead of bluegreen.rollout.completed. Align the mapping (and the doc comment/tests) with the real RolloutStrategy::name() values.
/// Build the full occurrence type from strategy name and phase transition
///
/// Maps strategy names to FALSE Protocol type prefixes:
/// - "canary" → "canary.rollout.*"
/// - "blue_green" → "bluegreen.rollout.*"
/// - "ab_testing" → "abtesting.rollout.*"
/// - "simple" → "rolling.rollout.*"
fn build_occurrence_type(strategy: &str, old_phase: Option<&Phase>, new_phase: &Phase) -> String {
    let prefix = match strategy {
        "blue_green" => "bluegreen",
        "ab_testing" => "abtesting",
        "simple" => "rolling",
        other => other, // "canary" passes through
    };
    let suffix = phase_to_occurrence_suffix(old_phase, new_phase);
    format!("{}.rollout.{}", prefix, suffix)

src/controller/prometheus_ab.rs:210

  • determine_experiment_conclusion has overlapping/likely-unreachable branches: the a_wins > 0 && b_wins == 0 and b_wins > 0 && a_wins == 0 cases already cover the scenario where all significant results agree, making the subsequent a_wins == significant_results.len() || b_wins == significant_results.len() branch redundant. Consider simplifying the logic to avoid confusion and ensure the chosen ABConclusionReason is intentional.
pub fn determine_experiment_conclusion(
    results: &[ABMetricResult],
) -> Option<(ABVariant, ABConclusionReason)> {
    if results.is_empty() {
        return None;
    }

    // Check if all significant metrics agree on a winner
    let significant_results: Vec<&ABMetricResult> =
        results.iter().filter(|r| r.is_significant).collect();

    if significant_results.is_empty() {
        return None;
    }

    // Count winners
    let mut a_wins = 0;
    let mut b_wins = 0;

    for result in &significant_results {
        match &result.winner {
            Some(ABVariant::A) => a_wins += 1,
            Some(ABVariant::B) => b_wins += 1,
            None => {}
        }
    }

    // All significant metrics agree
    if a_wins > 0 && b_wins == 0 {
        Some((ABVariant::A, ABConclusionReason::ConsensusReached))
    } else if b_wins > 0 && a_wins == 0 {
        Some((ABVariant::B, ABConclusionReason::ConsensusReached))
    } else if a_wins == significant_results.len() || b_wins == significant_results.len() {
        let winner = if a_wins > b_wins {
            ABVariant::A
        } else {
            ABVariant::B
        };
        Some((winner, ABConclusionReason::SignificanceReached))
    } else {
        None
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@yairfalse yairfalse merged commit 21a0e74 into main Feb 20, 2026
0 of 2 checks passed
@yairfalse yairfalse deleted the feature/update-sykli branch February 20, 2026 23:25
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.

2 participants