Featurevisor

Larger projects

Sets

Sets split one repository into independent projects. Each set has its own definitions, tests, datafiles and state files. Only featurevisor.config.js is shared.

When to use sets

Sets suit two situations:

  • Separate surfaces that share nothing. A storefront and an admin tool live in one repository, but share no attributes, segments or users. Each becomes a set, so a change to one set's definitions cannot reach the other's users.
  • Release lanes. dev, staging and production each hold a complete tree, and changes move forward through promotions, so production receives what staging already ran. Environments compares this with environments.

For other needs, something smaller does the job. Use environments for different rules per environment, namespaces to group keys, and targets to split a project into several datafiles.

Set up sets

Start a project with a storefront and an admin set, each with staging and production environments:

Command
npx @featurevisor/cli@latest init --example=sets

The examples on this page leave those environments out, so each feature has a single list of rules. With environments, each set's features group their rules by environment, as Environments shows.

To convert an existing project, turn sets on in the configuration:

featurevisor.config.js
module.exports = {
sets: true,
}

Then move each directory of definitions and tests into sets/<name>/. With sets on, definitions at the top level are ignored without a warning, so make sure nothing is left behind.

Directory structure

Each set has the layout of a whole project, and its directory name is its name:

Project
  • sets/
    • storefront/
      • attributes/
        • country.yml
        • userId.yml
      • segments/
        • netherlands.yml
      • features/
        • promoBanner.yml
      • targets/
        • all.yml
      • tests/
        • features/
          • promoBanner.spec.yml
        • segments/
          • netherlands.spec.yml
    • admin/
      • attributes/
        • role.yml
        • userId.yml
      • segments/
        • support.yml
      • features/
        • promoBanner.yml
      • targets/
        • all.yml
      • tests/
        • features/
          • promoBanner.spec.yml
        • segments/
          • support.spec.yml
  • A set can also have variables/ and schemas/.
  • Every set needs at least one target of its own.
  • Inside a set, directory names are fixed. Options such as featuresDirectoryPath do not apply, but setsDirectoryPath moves the whole sets directory.

The same key in two sets

Both sets define promoBanner, each with its own audience. The storefront shows it to Dutch visitors:

sets/storefront/features/promoBanner.yml
description: Storefront promotional banner
bucketBy: userId
rules:
- key: netherlands
conditions: netherlands
percentage: 100
- key: everyone
conditions: '*'
percentage: 0

The admin tool shows it to the support team, using an attribute the storefront does not have:

sets/admin/segments/support.yml
description: Support team members
conditions:
- attribute: role
operator: equals
value: support
sets/admin/features/promoBanner.yml
description: Admin promotional banner
bucketBy: userId
rules:
- key: support
conditions: support
percentage: 100
- key: everyone
conditions: '*'
percentage: 0

Sets cannot see each other. A storefront rule cannot use the admin's support segment, and role is not an attribute there.

Run commands per set

lint, test and build run every set, under a heading for each. Pass --set to run one:

Commands
npx featurevisor test --set=admin
npx featurevisor build --set=storefront

An unknown name fails and lists the sets that exist. Printing a datafile needs a set, plus --environment if the project has environments:

Command
npx featurevisor build \
--set=storefront \
--json \
--pretty

Datafiles, state and revisions

Each set's datafiles go under its own directory:

Command
tree datafiles
Output
datafiles
├── admin
│ ├── featurevisor-all.json
│ └── REVISION
├── REVISION
└── storefront
├── featurevisor-all.json
└── REVISION

With environments, the environment comes next, as in datafiles/storefront/production/featurevisor-all.json.

State files are kept per set in .featurevisor/sets/<set>/. The revision is shared. Every build moves it forward, and a build with --set leaves the other sets' datafiles at their previous revision. Build every set before you deploy the whole datafiles directory.

Load a set in your application

Each application loads the datafile of its own set, such as storefront/featurevisor-all.json. If one application needs two sets, give each its own SDK instance. Loading both into one instance would merge them, and one set's promoBanner would replace the other's.

Move changes between sets

When sets are release lanes, promotions copy definitions from one set to the next, and promotionFlows limits the direction they can go.

Previous
Namespaces