Skip to content

Commit

Permalink
feat: allow printing datafile per environment (#275)
Browse files Browse the repository at this point in the history
  • Loading branch information
fahad19 committed Mar 9, 2024
1 parent a34f69f commit 28b4a0f
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 43 deletions.
8 changes: 7 additions & 1 deletion docs/building-datafiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,18 @@ $ featurevisor build --revision 1.2.3

## Printing

You can print the contents of a datafile for a single feature without writing anything to disk by passing these flags:
You can print the contents of a datafile for a single feature in/or an environment without writing anything to disk by passing these flags:

```
$ featurevisor build --feature=foo --environment=production --print --pretty
```

Or if you with to print datafile containing all features for a specific environment:

```
$ featurevisor build --environment=production --print --pretty
```

This is useful primarily for debugging and testing purposes.

If you are an SDK developer in other languages besides JavaScript, you may want to use this handy command to get the generated datafile content in JSON format that you can use in your own [test runner](/docs/testing).
34 changes: 33 additions & 1 deletion packages/core/src/builder/buildDatafile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,45 @@ import {
VariableSchema,
} from "@featurevisor/types";

import { ProjectConfig } from "../config";
import { ProjectConfig, SCHEMA_VERSION } from "../config";
import { Datasource } from "../datasource";
import { extractAttributeKeysFromConditions, extractSegmentKeysFromGroupSegments } from "../utils";

import { getTraffic } from "./traffic";
import { getFeatureRanges } from "./getFeatureRanges";

export interface CustomDatafileOptions {
featureKey?: string;
environment: string;
projectConfig: ProjectConfig;
datasource: Datasource;
revision?: string;
}

export async function getCustomDatafile(options: CustomDatafileOptions): Promise<DatafileContent> {
let featuresToInclude;

if (options.featureKey) {
const requiredChain = await options.datasource.getRequiredFeaturesChain(options.featureKey);
featuresToInclude = Array.from(requiredChain);
}

const existingState = await options.datasource.readState(options.environment);
const datafileContent = await buildDatafile(
options.projectConfig,
options.datasource,
{
schemaVersion: SCHEMA_VERSION,
revision: options.revision || "tester",
environment: options.environment,
features: featuresToInclude,
},
existingState,
);

return datafileContent;
}

export interface BuildOptions {
schemaVersion: string;
revision: string;
Expand Down
17 changes: 8 additions & 9 deletions packages/core/src/builder/buildProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import * as path from "path";

import { SCHEMA_VERSION } from "../config";

import { buildDatafile } from "./buildDatafile";
import { getDatafileForFeature } from "../tester";
import { buildDatafile, getCustomDatafile } from "./buildDatafile";
import { Dependencies } from "../dependencies";

export interface BuildCLIOptions {
Expand All @@ -23,20 +22,20 @@ export async function buildProject(deps: Dependencies, cliOptions: BuildCLIOptio
* This build process does not write to disk, and prints only to stdout.
*
* This is ideally for test runners in other languages,
* when they wish to get datafile for a single feature,
* when they wish to get datafile for a single feature and/or environment,
* so they can run tests against their own SDKs in other languages.
*
* This way we centralize the datafile generation in one place,
* while tests can be run anywhere else.
*/
if (cliOptions.environment && cliOptions.feature && cliOptions.print) {
const datafileContent = await getDatafileForFeature(
cliOptions.feature,
cliOptions.environment,
if (cliOptions.environment && cliOptions.print) {
const datafileContent = await getCustomDatafile({
featureKey: cliOptions.feature,
environment: cliOptions.environment,
projectConfig,
datasource,
cliOptions.revision,
);
revision: cliOptions.revision,
});

if (cliOptions.pretty) {
console.log(JSON.stringify(datafileContent, null, 2));
Expand Down
37 changes: 5 additions & 32 deletions packages/core/src/tester/testFeature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,12 @@ import { createInstance, MAX_BUCKETED_NUMBER } from "@featurevisor/sdk";

import { Datasource } from "../datasource";
import { ProjectConfig } from "../config";
import { buildDatafile } from "../builder";
import { SCHEMA_VERSION } from "../config";
import { getCustomDatafile } from "../builder";

import { checkIfArraysAreEqual } from "./checkIfArraysAreEqual";
import { checkIfObjectsAreEqual } from "./checkIfObjectsAreEqual";
import { getFeatureAssertionsFromMatrix } from "./matrix";

export async function getDatafileForFeature(
featureKey: string,
environment: string,
projectConfig: ProjectConfig,
datasource: Datasource,
revision: string = "testing",
): Promise<DatafileContent> {
const requiredChain = await datasource.getRequiredFeaturesChain(featureKey);
const featuresToInclude = Array.from(requiredChain);

const existingState = await datasource.readState(environment);
const datafileContent = await buildDatafile(
projectConfig,
datasource,
{
schemaVersion: SCHEMA_VERSION,
revision,
environment: environment,
features: featuresToInclude,
},
existingState,
);

return datafileContent;
}

export async function testFeature(
datasource: Datasource,
projectConfig: ProjectConfig,
Expand Down Expand Up @@ -85,12 +58,12 @@ export async function testFeature(
const datafileContent =
typeof datafileContentByEnvironment[assertion.environment] !== "undefined"
? datafileContentByEnvironment[assertion.environment]
: await getDatafileForFeature(
test.feature,
assertion.environment,
: await getCustomDatafile({
featureKey: test.feature,
environment: assertion.environment,
projectConfig,
datasource,
);
});

if (options.showDatafile) {
console.log("");
Expand Down

0 comments on commit 28b4a0f

Please sign in to comment.