Repository navigation
[eas-cli] Add experimentation client - #4558
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4558 +/- ##
==========================================
+ Coverage 74.77% 74.92% +0.16%
==========================================
Files 1038 1046 +8
Lines 51083 51333 +250
Branches 11105 11152 +47
==========================================
+ Hits 38190 38457 +267
+ Misses 11903 11887 -16
+ Partials 990 989 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
8382e68 to
f21a70d
Compare
|
Subscribed to pull request
Generated by CodeMention Warning: The preamble and epilogue options in commentConfiguration are deprecated. Use template instead. |
|
This looks good to me, but wanted to have a more frequent-flyer on eas-cli weigh in. @hSATAC would you be able to take a look? |
There was a problem hiding this comment.
Looks good! My one comment is that I'm wondering if experimentation should be disabled in CI. It's likely that a lot of the experiments wouldn't be applicable, but I guess it could have the potential to cause inconsistent results, or at least inconsistent logs (which sometimes matters in debugging). But, I guess suppose experiments are enabled on the eas build command, if they're not relevant to CI / EAS Build / Workflows, then we'd spend time querying on those job runs where we wouldn't need to. And with CI, those "users" are often bots or our Github context, so they're problably n/a for experiments. Oh, I see you disabled based on bot token, so practically speaking, that covers most scenarios I'm thinking of- it might be good to also disable on CI=1 for thoroughness, tho
My Claude had a comment about how on project-scoped experiments, the app config is evaluated for any command that opts into one, even if the subcommand or option doesn't need it. Most of the EAS CLI evaluates app config anyway, so I can't honestly think of an example where that would. be a problem. But my ears perked up because app config eval executes custom code from. the user, and there have been scenarios where it fails for weird reasons (like node version stuff) and it tends to be confusing, so it had me thinking if we could end up evaluating app config where we didn't previously need to.
The more I think about this, the less likely it sounds, because you can't even determine project ID without a config eval, and project ID's are needed pretty much everywhere. And the places where we get that weird behavior reported tend to be in CI / EAS.
| authInfo: { | ||
| accessToken: string | null; | ||
| sessionSecret: string | null; | ||
| }, |
hSATAC
left a comment
There was a problem hiding this comment.
Looks good overall. I left two small questions inline. I mostly contribute to the worker side, so I'd appreciate @douglowder taking a look at how this fits into the broader eas-cli architecture. I'll leave the approval to Doug.
| return null; | ||
| } | ||
|
|
||
| const { exp } = getConfig(projectDir, { skipSDKVersionRequirement: true, skipPlugins: true }); |
There was a problem hiding this comment.
Following up on Keith's point: skipPlugins still evaluates dynamic config, so this adds an extra config evaluation inside the CLI process. The catch handles throws, but not side effects like process.exit() or slow synchronous work.
Could we have commands pass the account they already resolved via getAccountNamespace(name, { accountId })? That would avoid evaluating config just to initialize experiments.
| experimentation { | ||
| userConfig | ||
| accountConfig | ||
| deviceConfig |
There was a problem hiding this comment.
Are CLI experiments going to use their own namespaces? This returns the same configs the website uses, but device bucketing uses the analytics UUID here rather than IP. Reading a website experiment would also log an exposure for it, so we'd need to filter those out of the website analysis.
There was a problem hiding this comment.
Good Q! CLI experiments will use their own namespaces with a cli- prefix. Exposure logs between website/CLI go to different BQ datasets so we don't cross-contaminate the data. We may want to share an account or user-level experiment between the website and the CLI in the future. Added a comment about not sharing device-level namespaces.
976911d to
f9d39e3
Compare
🤖 AI code reviewDecision: Ready for human review Overall PR risk: Medium. The change is additive. It adds an experimentation client and optional parameters to shared functions like No findings. This review is advisory — it never blocks a merge and never auto-approves. |
|
eas-cli now uses changesets for changelogs (#4580). The required "Check for a changeset" check fails on PRs that edit To update this PR:
The release adds the PR link and the author to the entry. If this PR needs no changelog entry, revert the |
5e2ff4b to
c760903
Compare
8252c48 to
2ad44d0
Compare
|
✅ Thank you for adding a changeset! |

Why
Run experiments in the EAS CLI.
How
The implementation is a port from our website's experimentation client. Each command can opt in with
ContextOptions.Experimentation. The context returns a lazy client and the firstgetClientAsync()call builds it: fetches the experiments config, resolves the bucketing units, and evaluates variants. The bucketing unit depends on the scope. User: actor ID, Account: account ID the command passes togetAccountNamespace, Device: existing analytics device ID (same UUID used with the RudderStackanonymousId).Experiment errors are never shown to the user (fail silently) and fall back to defaults. The config fetch is capped at 3 seconds, so a slow network returns defaults instead of delaying the command. Disabling analytics turns off all experiments. CI runs skip experiments. Overrides with
EAS_EXPERIMENT_OVERRIDEforces a variant for QA without exposure logging.Test Plan
See example experiments in stacked PRs: #4631, #4633
To test locally:
eas whoamior see examples in stacked PRs) with the experimentation context and variant logs:Run the command with
EXPO_DEBUG=1. Then verify the following steps.Bucketing
unitis correct for each device, account, and user-level experiment and anExperiment Viewedexposure is logged to our staging data store. Bucketing remains consistent across reruns.