Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CHORE] document canary feature-flag infra #6859

Merged
merged 2 commits into from
Dec 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 0 additions & 95 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,101 +106,6 @@ All commits should be tagged. Tags are denoted by square brackets (`[]`) and com
In general almost all commits should fall into one of the above categories. In the cases where they don't please submit
your PR untagged.

#### Developing a New Feature with in-progress-feature Flags

Sometimes a new feature can't be completed all at once, but portions
of it can be landed to help parallelize the effort and make the review
process simpler.

`in-progress-feature` flags allow for code to be present on the `master`
branch but stripped from any build that isn't.

These flags have three states. Locally here means that a developer is
working within the `addon` itself. Locally linking `ember-data` to
another project or using a `master` build will not make code behind
the flags available unless `isDevelopingAddon` in `index.js` is modified
to return `true`.

- `false`: the feature is only available locally and the code behind the
flag is stripped at all times and never included in test runs. To develop
on this feature use `--enable-in-progress-flag="desired-flag-name,another-flag-name"`
when running a command. This flag will never be active in `CI` jobs
meaning that both tests and code wrapped in a check for this flag will
not run.

- `null`: The same as `false` except the `Enabled In-Progress Features`
job in `CI` will activate the flag to ensure it passes tests.
Use this for features that are nearing delivery and need protection
against regressions but are not quite polished off yet.

Other test runs and `CI` will still default the flag to `false` to ensure
that what we would release (were we to release master) works as
expected.

The `--enable-in-progress` flag and the Travis Job `Enabled In-Progress Features`
will run the tests with any flags set to `null` enabled to prevent
regressions.

- `true`: Indicates that this feature is "complete". Features set to
`true` will be included in any `release` published while the flag
is in that state, any build from `master` and all `CI` jobs.

This is a sign that the feature has entered a final testing phase
and the in-progress flags for the feature should be removed
before a stable release is published.

Sometimes a nearly releasable feature may encounter problems late
in the release cycle. For such problems, the flag should be moved
back to the `null` state prior to doing a release.

Versions published with a flag set to `true` will include that
feature.

1. Add your new feature flag to the [config/in-progress-features.json](https://github.com/emberjs/data/blob/master/config/in-progress-features.json) file with the `ds-` prefix.

```js
{
"ds-mynew-feature": false
}
```

Give it a default of `false` so it will not be used in production builds.

2. Import `isEnabled` from `ember-data/-private`, wrapping any new
code with your feature:

```js
import { isEnabled } from 'ember-data/-private';

if (isEnabled('ds-mynew-feature')) {
// ... any additional code
} else {
// ... any previous code that may have been overwritten
}
```

3. Similarly, you will want to wrap any new or edited tests with the same
feature flag.

```js
import { isEnabled } from 'ember-data/-private';

if (isEnabled('ds-mynew-feature')) {
test('test for new feature', function(assert) {
// ...
});
}
```

This will ensure these feature tests are only run when then feature is included in the build for `ember-data`.

4. Commit your work. For more information about commit prefixes see [Commit Tagging](#commit-tagging).

5. Push to your fork and submit a pull request. Please provide us with some
explanation of why you made the changes you made. For new features make sure to
explain a standard use case to us. Use the commit tagging guidelines for the PR
title.

## Notes

- Commit tagging section taken from [ember.js](https://github.com/emberjs/ember.js/blob/5641c3089180bdd1d4fa54e9dd2d3ac285f088e4/CONTRIBUTING.md#commit-tagging)
168 changes: 161 additions & 7 deletions packages/canary-features/addon/default-features.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,164 @@
/**
@module @ember-data/canary-features
*/
* ## Canary Features
*
* EmberData allows users to test features that are implemented but not yet
* available even in canary.
*
* Typically these features represent work that might introduce a new concept,
* new API, change an API, or risk an unintended change in behavior to consuming
* applications.
*
* Such features have their implementations guarded by a "feature flag", and the
* flag is only activated once the core-data team is prepared to ship the work
* in a canary release.
*
* ### Installing Canary
*
* To test a feature you MUST be using a canary build. Canary builds are published
* to `npm` and can be installed using a precise tag (such as `[email protected]`)
* or by installing the latest dist-tag published to the `canary` channel.
*
* *Using `npm` to install the latest canary*
*
* ```cli
* npm install --save-dev ember-data@canary
* ```
*
* *Using `yarn` to install the latest canary*
*
* ```cli
* yarn add ember-data@canary
* ```
*
* ### Activating a Canary Feature
*
* Once you have installed canary, feature-flags can be activated at build-time by an environment
* variable or at runtime using `window.EmberDataENV`.
*
* The "off" branch of feature-flagged code is always stripped from production builds, so you
* MUST use the build-time environment variable to activate a flag if testing production.
*
* The list of available feature-flags is located [here](https://github.com/emberjs/data/tree/master/packages/canary-features/addon/default-features.ts "List of EmberData FeatureFlags")
*
* #### Runtime Configuration
*
* To configure feature-flags at runtime you will want to configure `window.EmberDataENV = {}` appropriately.
* You should add this global property in your app prior to your application booting. At the top of
* your `app.js` file is a convenient location, as is within ` index.html` as a script running prior
* to loading any other scripts.
*
* *Example activating a single feature flags*
*
* ```js
* window.EmberDataENV = {
* FEATURES: {
* RECORD_DATA_ERRORS: true,
* }
* }
* ```
*
* *Example activating multiple feature flags*
*
* ```js
* window.EmberDataENV = {
* FEATURES: {
* RECORD_DATA_ERRORS: true,
* RECORD_DATA_STATE: true,
* }
* }
* ```
*
* *Example activating all feature flags*
*
* ```js
* window.EmberDataENV = {
* ENABLE_OPTIONAL_FEATURES: true
* }
* ```
*
* #### Build Time Configuration
*
* *Example activating a single feature flags*
*
* ```js
* EMBER_DATA_FEATURE_OVERRIDE=REQUEST_SERVICE ember build
* ```
*
* *Example activating multiple feature flags*
*
* ```js
* EMBER_DATA_FEATURE_OVERRIDE=REQUEST_SERVICE,CUSTOM_MODEL_CLASS ember build
* ```
*
* *Example activating all feature flags*
*
* ```js
* EMBER_DATA_FEATURE_OVERRIDE=ENABLE_ALL_OPTIONAL ember build
* ```
*
* ### Preparing an Addon to use a Canary Feature
*
* For most addons and most features simple version detection should be
* enough. Using the provided version compatibility helpers from
* [ember-compatibility-helpers](https://github.com/pzuraq/ember-compatibility-helpers)
* the following can be done:
*
* ```js
* if (gte('@ember-data/store', '3.12.0')) {
*
* } else {
*
* }
* ```
*
* For addons needing more advanced detection [babel-plugin-debug-macros](https://github.com/ember-cli/babel-plugin-debug-macros)
* can be leveraged to provide code-stripping based on feature presence. For example in your addon's `index.js`:
*
* ```js
* function debugMacros(features) {
* let plugins = [
* [
* require.resolve('babel-plugin-debug-macros'),
* {
* flags: [
* {
* source: '<addon-name>/feature-flags',
* flags: features,
* },
* ],
* },
* '<addon-name>/canary-features-stripping',
* ],
* ];
*
* return plugins;
* }
*
* module.exports = {
* name: '<addon-name>',
*
* init() {
* this._super.init.apply(this, arguments);
*
* let features;
* try {
* features = this.project.require('@ember-data/private-build-infra/src/features')();
* } catch (e) {
* features = { CUSTOM_MODEL_CLASS: false };
* }
*
* this.options = this.options || {};
* this.options.babel = this.options.babel || {};
* // this ensures that the same `@ember-data/canary-features` processing that the various
* // ember-data addons do is done for this addon
* this.options.babel.plugins = [...debugMacros(features)];
* }
* }
* ```
*
* @module @ember-data/canary-features
* @main @ember-data/canary-features
*/
/*
This list of features is used both at build time (by `@ember-data/private-build-infra`)
and at runtime (by `@ember-data/canary-features`).
Expand All @@ -10,11 +168,7 @@
- true - The feature is enabled at all times, and cannot be disabled.
- false - The feature is disabled at all times, and cannot be enabled.
- null - The feature is disabled by default, but can be enabled at runtime via `EmberDataENV`.

@module @ember-data/canary-features
@main @ember-data/canary-features
@private
*/
*/
export default {
SAMPLE_FEATURE_FLAG: null,
RECORD_DATA_ERRORS: null,
Expand Down