Skip to main content

Commands

Generating code for an mobile application

The simplest invocation is in this form:

% nimbus-fml generate --language <LANGUAGE> --channel <CHANNEL> <INPUT> <OUTPUT>
  • LANGUAGE can be kotlin or swift.
  • CHANNEL is one of the channels specified in the FML file.
  • INPUT may be a local file or directory.
  • OUTPUT should be a local file or directory.

If INPUT is a directory, it is recursively searches for any files with names ending in .fml.yaml.

This command should be called at build time of components and the build time of the application.

Adding repo-files

Adding repo files can be done with one or more --repo-file argument.

% nimbus-fml generate --language <LANGUAGE> --repo-file ./app-structure.json <INPUT> <OUTPUT>

Getting different versions of the same manifest

For remote manifests, the default branch to fetch from is main. This can be changed with the --ref option.

Using a ref is equivalent to taking the remote repo of the manifest path and creating a repo-file with that repo mapped to the given ref.

This command uses feature manifest from the releases_v118 branch of the https://github.com/mozilla-mobile/firefox-android repository:

% nimbus-fml generate --language <LANGUAGE> --ref releases_v118 @mozilla-mobile/firefox-android/fenix/app/nimbus.fml.yaml <OUTPUT>

Caching remote files

% nimbus-fml generate --language <LANGUAGE> --channel CHANNEL --cache-dir ./build/cache-dir <INPUT> <OUTPUT>

For include and import directives in the FML, a remote file may be referenced. The cache directory is a local cache of these remote files.

For each of the following, --ref, --cache-dir and --repo-file flags are supported.

Generating a manifest file for experimenter

The reason to use a custom manifest format a language specific JSON serialization library is to do with keeping the code in sync with the experimenter web server.

For legacy reasons, this is a different format of yaml file, which should be checked in to version control and is periodically pulled in by experimenter.

% nimbus-fml generate-experimenter <INPUT> <OUTPUT>

This should only be called at the application level, with the one main fml file as an input.

--cache-dir, --ref, and --repo-file arguments are also supported.

Validating a manifest file

% nimbus-fml validate <INPUT>

This gives a view of the validation process for all channels.

% nimbus-fml validate @mozilla-mobile/firefox-android/fenix/app/nimbus.fml.yaml

gives

ℹ️ Loaded modules:
- https://raw.githubusercontent.com/mozilla-mobile/firefox-android/main/fenix/app/onboarding.fml.yaml
- https://raw.githubusercontent.com/mozilla-mobile/firefox-android/main/fenix/app/nimbus.fml.yaml
- https://raw.githubusercontent.com/mozilla-mobile/firefox-android/main/fenix/app/pbm.fml.yaml
- https://raw.githubusercontent.com/mozilla-mobile/firefox-android/main/android-components/components/browser/engine-gecko/geckoview.fml.yaml
- https://raw.githubusercontent.com/mozilla-mobile/firefox-android/main/android-components/components/service/nimbus/messaging.fml.yaml

Validating manifest for different channels:
✅ release.............valid
✅ beta................valid
✅ nightly.............valid
✅ developer...........valid

Re-write a complicated distributed manifest into a single file

The FML spec allows you to import and include dependencies' manifests. This is convenient for engineers to place the feature manifest close to where the feature code lives.

However, for some circumstances, it may not be good for packagers or distributers of the software: e.g. if the file is to be distributed with the software.

To help this, the single-file command is used to merge all imports and includes into the top level file, with a single channel.

% nimbus-fml single-file --channel release @mozilla-mobile/firefox-android/fenix/app/nimbus.fml.yaml single-file.fml.yaml

Generating a machine readable overview of a feature

% nimbus-fml info [--channel CHANNEL] [--json] <MANIFEST> [--feature FEATURE]

This prints a simplified YAML or JSON representation for each feature. e.g.

{
"file": "https://raw.githubusercontent.com/mozilla-mobile/firefox-android/main/fenix/app/nimbus.fml.yaml",
"features": {
"homescreen": {
"description": "The homescreen that the user goes to when they press home or new tab.",
"types": [
"Boolean",
"HomeScreenSection",
"Map<HomeScreenSection, Boolean>"
],
"hashes": {
"schema": "7a15570b",
"defaults": "423ab0bd"
}
}
}
}

Hashes

The hashes object shows truncated SHA256 hashes for:

  • the schema (the types, variable names, the enum variants available)
  • the defaults (the default values of the feature variables)
tip
  • Changes in the schema hash might indicate a change in the feature code.
  • Changes in the defaults hash would indicate a different configuration being used for the same code.
  • Changes in the schema hash will almost always be accompanied by a change in the defaults hash, with the exception of changing variable types from a String type to a string-alias type (or vice-versa).

Types

The types list is a sorted list of the types involved used to define the feature. This list may be used as a proxy for a measure of complexity of the feature configuration space.

Feature metadata

In addition, the feature metadata is also displayed.

If a --feature argument is supplied, then restrict the output to just this feature.

If a --channel argument is supplied, then use this channel. This will affect the defaults hashes.

Using info with JQ

You can use --json JQ to output some interesting data:

Get the features for this app:

% nimbus-fml info <INPUT> --json | jq '.features|keys'

Get the channels for this app:

% nimbus-fml channels <INPUT> --json

Get the hashes for just the homescreen feature:

% nimbus-fml info <INPUT> --json | jq '.features.homescreen.hashes'

--cache-dir, --ref and --repo-file arguments are also supported.