mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
feat: add stale property on toggle (#619)
This commit is contained in:
parent
e4faf3022c
commit
83dda55172
@ -20,6 +20,7 @@ This endpoint is the one all admin ui should use to fetch all available feature
|
||||
"description": "lorem ipsum",
|
||||
"type": "release",
|
||||
"enabled": false,
|
||||
"stale": false,
|
||||
"strategies": [
|
||||
{
|
||||
"name": "default",
|
||||
@ -41,6 +42,7 @@ This endpoint is the one all admin ui should use to fetch all available feature
|
||||
"name": "Feature.B",
|
||||
"description": "lorem ipsum",
|
||||
"enabled": true,
|
||||
"stale": false,
|
||||
"strategies": [
|
||||
{
|
||||
"name": "ActiveForUserWithId",
|
||||
@ -71,6 +73,7 @@ Used to fetch details about a specific featureToggle. This is mostly provded to
|
||||
"description": "lorem ipsum..",
|
||||
"type": "release",
|
||||
"enabled": false,
|
||||
"stale": false,
|
||||
"strategies": [
|
||||
{
|
||||
"name": "default",
|
||||
@ -93,6 +96,7 @@ Used to fetch details about a specific featureToggle. This is mostly provded to
|
||||
"description": "lorem ipsum..",
|
||||
"type": "release",
|
||||
"enabled": false,
|
||||
"stale": false,
|
||||
"strategies": [
|
||||
{
|
||||
"name": "default",
|
||||
@ -123,6 +127,7 @@ Returns 200-respose if the feature toggle was created successfully.
|
||||
"description": "lorem ipsum..",
|
||||
"type": "release",
|
||||
"enabled": false,
|
||||
"stale": false,
|
||||
"strategies": [
|
||||
{
|
||||
"name": "default",
|
||||
@ -189,6 +194,65 @@ None
|
||||
"description": "lorem ipsum..",
|
||||
"type": "release",
|
||||
"enabled": false,
|
||||
"stale": false,
|
||||
"strategies": [
|
||||
{
|
||||
"name": "default",
|
||||
"parameters": {}
|
||||
}
|
||||
],
|
||||
"variants": []
|
||||
}
|
||||
```
|
||||
|
||||
### Mark a Feature Toggle as "stale"
|
||||
|
||||
`POST: http://unleash.host.com/api/admin/features/:featureName/stale/on`
|
||||
|
||||
Used to mark a feature toggle as stale (deprecated). The :featureName must match an existing Feature Toggle. Returns 200-response if the feature toggle was enabled successfully.
|
||||
|
||||
**Body**
|
||||
|
||||
None
|
||||
|
||||
**Example response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Feature.A",
|
||||
"description": "lorem ipsum..",
|
||||
"type": "release",
|
||||
"enabled": true,
|
||||
"stale": true,
|
||||
"strategies": [
|
||||
{
|
||||
"name": "default",
|
||||
"parameters": {}
|
||||
}
|
||||
],
|
||||
"variants": []
|
||||
}
|
||||
```
|
||||
|
||||
### Mark a Feature Toggle as "active"
|
||||
|
||||
`POST: http://unleash.host.com/api/admin/features/:featureName/stale/off`
|
||||
|
||||
Used to mark a feature toggle active (remove stale marking). The :featureName must match an existing Feature Toggle. Returns 200-response if the feature toggle was disabled successfully.
|
||||
|
||||
**Body**
|
||||
|
||||
None
|
||||
|
||||
**Example response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Feature.A",
|
||||
"description": "lorem ipsum..",
|
||||
"type": "release",
|
||||
"enabled": false,
|
||||
"stale": false,
|
||||
"strategies": [
|
||||
{
|
||||
"name": "default",
|
||||
@ -218,6 +282,7 @@ Used to fetch list of archived feature toggles
|
||||
"description": "lorem ipsum",
|
||||
"type": "release",
|
||||
"enabled": false,
|
||||
"stale": false,
|
||||
"strategies": [
|
||||
{
|
||||
"name": "default",
|
||||
|
@ -29,6 +29,7 @@ This endpoint should never return anything besides a valid _20X or 304-response_
|
||||
"description": "lorem ipsum",
|
||||
"type": "release",
|
||||
"enabled": false,
|
||||
"stale": false,
|
||||
"strategies": [
|
||||
{
|
||||
"name": "default",
|
||||
@ -43,6 +44,7 @@ This endpoint should never return anything besides a valid _20X or 304-response_
|
||||
"type": "killswitch",
|
||||
"description": "lorem ipsum",
|
||||
"enabled": true,
|
||||
"stale": false,
|
||||
"strategies": [
|
||||
{
|
||||
"name": "ActiveForUserWithId",
|
||||
@ -80,6 +82,7 @@ Used to fetch details about a specific feature toggle. This is mainly provided t
|
||||
"description": "lorem ipsum..",
|
||||
"type": "release",
|
||||
"enabled": false,
|
||||
"stale": false,
|
||||
"strategies": [
|
||||
{
|
||||
"name": "default",
|
||||
|
@ -15,6 +15,7 @@ const FEATURE_COLUMNS = [
|
||||
'description',
|
||||
'type',
|
||||
'enabled',
|
||||
'stale',
|
||||
'strategies',
|
||||
'variants',
|
||||
'created_at',
|
||||
@ -100,6 +101,7 @@ class FeatureToggleStore {
|
||||
description: row.description,
|
||||
type: row.type,
|
||||
enabled: row.enabled > 0,
|
||||
stale: row.stale,
|
||||
strategies: row.strategies,
|
||||
variants: row.variants,
|
||||
createdAt: row.created_at,
|
||||
@ -112,6 +114,7 @@ class FeatureToggleStore {
|
||||
description: data.description,
|
||||
type: data.type,
|
||||
enabled: data.enabled ? 1 : 0,
|
||||
stale: data.stale,
|
||||
archived: data.archived ? 1 : 0,
|
||||
strategies: JSON.stringify(data.strategies),
|
||||
variants: data.variants ? JSON.stringify(data.variants) : null,
|
||||
|
@ -54,6 +54,7 @@ const featureShema = joi
|
||||
.keys({
|
||||
name: nameType,
|
||||
enabled: joi.boolean().default(false),
|
||||
stale: joi.boolean().default(false),
|
||||
type: joi.string().default('release'),
|
||||
description: joi
|
||||
.string()
|
||||
|
@ -19,6 +19,7 @@ test('should be valid toggle name', t => {
|
||||
name: 'app.name',
|
||||
type: 'release',
|
||||
enabled: false,
|
||||
stale: false,
|
||||
strategies: [{ name: 'default' }],
|
||||
};
|
||||
|
||||
@ -31,6 +32,7 @@ test('should strip extra variant fields', t => {
|
||||
name: 'app.name',
|
||||
type: 'release',
|
||||
enabled: false,
|
||||
stale: false,
|
||||
strategies: [{ name: 'default' }],
|
||||
variants: [
|
||||
{
|
||||
@ -51,6 +53,7 @@ test('should allow weightType=fix', t => {
|
||||
name: 'app.name',
|
||||
type: 'release',
|
||||
enabled: false,
|
||||
stale: false,
|
||||
strategies: [{ name: 'default' }],
|
||||
variants: [
|
||||
{
|
||||
@ -70,6 +73,7 @@ test('should disallow weightType=unknown', t => {
|
||||
name: 'app.name',
|
||||
type: 'release',
|
||||
enabled: false,
|
||||
stale: false,
|
||||
strategies: [{ name: 'default' }],
|
||||
variants: [
|
||||
{
|
||||
@ -92,6 +96,7 @@ test('should be possible to define variant overrides', t => {
|
||||
name: 'app.name',
|
||||
type: 'release',
|
||||
enabled: false,
|
||||
stale: false,
|
||||
strategies: [{ name: 'default' }],
|
||||
variants: [
|
||||
{
|
||||
@ -119,6 +124,7 @@ test('variant overrides must have corect shape', async t => {
|
||||
name: 'app.name',
|
||||
type: 'release',
|
||||
enabled: false,
|
||||
stale: false,
|
||||
strategies: [{ name: 'default' }],
|
||||
variants: [
|
||||
{
|
||||
@ -147,6 +153,7 @@ test('should keep constraints', t => {
|
||||
name: 'app.constraints',
|
||||
type: 'release',
|
||||
enabled: false,
|
||||
stale: false,
|
||||
strategies: [
|
||||
{
|
||||
name: 'default',
|
||||
|
@ -35,6 +35,8 @@ class FeatureController extends Controller {
|
||||
this.post('/:featureName/toggle', this.toggle, UPDATE_FEATURE);
|
||||
this.post('/:featureName/toggle/on', this.toggleOn, UPDATE_FEATURE);
|
||||
this.post('/:featureName/toggle/off', this.toggleOff, UPDATE_FEATURE);
|
||||
this.post('/:featureName/stale/on', this.staleOn, UPDATE_FEATURE);
|
||||
this.post('/:featureName/stale/off', this.staleOff, UPDATE_FEATURE);
|
||||
}
|
||||
|
||||
async getAllToggles(req, res) {
|
||||
@ -126,21 +128,29 @@ class FeatureController extends Controller {
|
||||
const name = req.params.featureName;
|
||||
const feature = await this.featureToggleStore.getFeature(name);
|
||||
const enabled = !feature.enabled;
|
||||
this._toggle(enabled, req, res);
|
||||
this._updateField('enabled', enabled, req, res);
|
||||
} catch (error) {
|
||||
handleErrors(res, this.logger, error);
|
||||
}
|
||||
}
|
||||
|
||||
async toggleOn(req, res) {
|
||||
this._toggle(true, req, res);
|
||||
this._updateField('enabled', true, req, res);
|
||||
}
|
||||
|
||||
async toggleOff(req, res) {
|
||||
this._toggle(false, req, res);
|
||||
this._updateField('enabled', false, req, res);
|
||||
}
|
||||
|
||||
async _toggle(enabled, req, res) {
|
||||
async staleOn(req, res) {
|
||||
this._updateField('stale', true, req, res);
|
||||
}
|
||||
|
||||
async staleOff(req, res) {
|
||||
this._updateField('stale', false, req, res);
|
||||
}
|
||||
|
||||
async _updateField(field, value, req, res) {
|
||||
const { featureName } = req.params;
|
||||
const userName = extractUser(req);
|
||||
|
||||
@ -149,7 +159,7 @@ class FeatureController extends Controller {
|
||||
featureName,
|
||||
);
|
||||
|
||||
feature.enabled = enabled;
|
||||
feature[field] = value;
|
||||
await this.eventStore.store({
|
||||
type: FEATURE_UPDATED,
|
||||
createdBy: userName,
|
||||
|
17
migrations/20200806091734-add-stale-flag-to-features.js
Normal file
17
migrations/20200806091734-add-stale-flag-to-features.js
Normal file
@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
exports.up = function(db, cb) {
|
||||
return db.addColumn(
|
||||
'features',
|
||||
'stale',
|
||||
{
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
cb,
|
||||
);
|
||||
};
|
||||
|
||||
exports.down = function(db, cb) {
|
||||
return db.removeColumn('features', 'stale', cb);
|
||||
};
|
@ -87,7 +87,7 @@
|
||||
"prom-client": "^12.0.0",
|
||||
"response-time": "^2.3.2",
|
||||
"serve-favicon": "^2.5.0",
|
||||
"unleash-frontend": "3.4.1-0",
|
||||
"unleash-frontend": "3.5.0-0",
|
||||
"yargs": "^15.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -5616,10 +5616,10 @@ universalify@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
|
||||
|
||||
unleash-frontend@3.4.1-0:
|
||||
version "3.4.1-0"
|
||||
resolved "https://registry.yarnpkg.com/unleash-frontend/-/unleash-frontend-3.4.1-0.tgz#480731a753059ad4b38c98b9a5f014eaa44d912b"
|
||||
integrity sha512-skx+SlOFPHcrrQlY5UhNV6stxblUNaB0mGbZfbh7CdIuWMs1Y+KxVoorTqDaHV0zhyxKQvngzZOd696VnMxA4w==
|
||||
unleash-frontend@3.5.0-0:
|
||||
version "3.5.0-0"
|
||||
resolved "https://registry.yarnpkg.com/unleash-frontend/-/unleash-frontend-3.5.0-0.tgz#e3d3da3e3e8aad03195190cc913f3d2293672305"
|
||||
integrity sha512-S+myY4sQZH3Mx3Q/RsKngee1WSX4ndffqup+oQxLsoKQSNiKwtjiA1KnGugeM+SNLIUVgi+b+3JPKWXxkEjw4g==
|
||||
|
||||
unpipe@1.0.0, unpipe@~1.0.0:
|
||||
version "1.0.0"
|
||||
|
Loading…
Reference in New Issue
Block a user