diff options
Diffstat (limited to 'toolkit/components/normandy/actions/schemas')
4 files changed, 574 insertions, 0 deletions
diff --git a/toolkit/components/normandy/actions/schemas/README.md b/toolkit/components/normandy/actions/schemas/README.md new file mode 100644 index 0000000000..06a7dd4b15 --- /dev/null +++ b/toolkit/components/normandy/actions/schemas/README.md @@ -0,0 +1,13 @@ +# Normandy Action Argument Schemas + +This is a collection of schemas describing the arguments expected by Normandy +actions. Its primary purpose is to be used in the Normandy server and Delivery +Console to validate data and provide better user interactions. + +# Contributing + +Modifications to this package are made as part of mozilla-central following +standard procedures: push a patch to Phabricator as part of a bug. + +To release, bump the package version and land that, as above -- it can be part +of another patch -- and then `cd` to this directory and `npm publish`. diff --git a/toolkit/components/normandy/actions/schemas/export_json.js b/toolkit/components/normandy/actions/schemas/export_json.js new file mode 100644 index 0000000000..940db247aa --- /dev/null +++ b/toolkit/components/normandy/actions/schemas/export_json.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* eslint-env node */ + +/** + * This script exports the schemas from this package in JSON format, for use by + * other tools. It is run as a part of the publishing process to NPM. + */ + +const fs = require("fs"); +const schemas = require("./index.js"); + +fs.writeFile("./schemas.json", JSON.stringify(schemas), err => { + if (err) { + console.error("error", err); + } +}); diff --git a/toolkit/components/normandy/actions/schemas/index.js b/toolkit/components/normandy/actions/schemas/index.js new file mode 100644 index 0000000000..0aa30278ea --- /dev/null +++ b/toolkit/components/normandy/actions/schemas/index.js @@ -0,0 +1,530 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var EXPORTED_SYMBOLS = ["ActionSchemas"]; + +const ActionSchemas = { + "console-log": { + $schema: "http://json-schema.org/draft-04/schema#", + title: "Log a message to the console", + type: "object", + required: ["message"], + properties: { + message: { + description: "Message to log to the console", + type: "string", + default: "", + }, + }, + }, + + "messaging-experiment": { + $schema: "http://json-schema.org/draft-04/schema#", + title: "Messaging Experiment", + type: "object", + required: ["slug", "branches", "isEnrollmentPaused"], + properties: { + slug: { + description: "Unique identifier for this experiment", + type: "string", + pattern: "^[A-Za-z0-9\\-_]+$", + }, + isEnrollmentPaused: { + description: "If true, new users will not be enrolled in the study.", + type: "boolean", + default: true, + }, + branches: { + description: "List of experimental branches", + type: "array", + minItems: 1, + items: { + type: "object", + required: ["slug", "value", "ratio", "groups"], + properties: { + slug: { + description: + "Unique identifier for this branch of the experiment.", + type: "string", + pattern: "^[A-Za-z0-9\\-_]+$", + }, + value: { + description: "Message content.", + type: "object", + properties: {}, + }, + ratio: { + description: + "Ratio of users who should be grouped into this branch.", + type: "integer", + minimum: 1, + }, + groups: { + description: + "A list of experiment groups that can be used to exclude or select related experiments. May be empty.", + type: "array", + items: { + type: "string", + description: "Identifier of the group", + }, + }, + }, + }, + }, + }, + }, + + "preference-rollout": { + $schema: "http://json-schema.org/draft-04/schema#", + title: "Change preferences permanently", + type: "object", + required: ["slug", "preferences"], + properties: { + slug: { + description: + "Unique identifer for the rollout, used in telemetry and rollbacks", + type: "string", + pattern: "^[a-z0-9\\-_]+$", + }, + preferences: { + description: "The preferences to change, and their values", + type: "array", + minItems: 1, + items: { + type: "object", + required: ["preferenceName", "value"], + properties: { + preferenceName: { + description: "Full dotted-path of the preference being changed", + type: "string", + }, + value: { + description: "Value to set the preference to", + type: ["string", "integer", "boolean"], + }, + }, + }, + }, + }, + }, + + "preference-rollback": { + $schema: "http://json-schema.org/draft-04/schema#", + title: "Undo a preference rollout", + type: "object", + required: ["rolloutSlug"], + properties: { + rolloutSlug: { + description: "Unique identifer for the rollout to undo", + type: "string", + pattern: "^[a-z0-9\\-_]+$", + }, + }, + }, + + "addon-study": { + $schema: "http://json-schema.org/draft-04/schema#", + title: "Enroll a user in an opt-out SHIELD study", + type: "object", + required: [ + "name", + "description", + "addonUrl", + "extensionApiId", + "isEnrollmentPaused", + ], + properties: { + name: { + description: "User-facing name of the study", + type: "string", + minLength: 1, + }, + description: { + description: "User-facing description of the study", + type: "string", + minLength: 1, + }, + addonUrl: { + description: "URL of the add-on XPI file", + type: "string", + format: "uri", + minLength: 1, + }, + extensionApiId: { + description: + "The record ID of the extension used for Normandy API calls.", + type: "integer", + }, + isEnrollmentPaused: { + description: "If true, new users will not be enrolled in the study.", + type: "boolean", + default: true, + }, + }, + }, + + "addon-rollout": { + $schema: "http://json-schema.org/draft-04/schema#", + title: "Install add-on permanently", + type: "object", + required: ["extensionApiId", "slug"], + properties: { + extensionApiId: { + description: + "The record ID of the extension used for Normandy API calls.", + type: "integer", + }, + slug: { + description: + "Unique identifer for the rollout, used in telemetry and rollbacks.", + type: "string", + pattern: "^[a-z0-9\\-_]+$", + }, + }, + }, + + "addon-rollback": { + $schema: "http://json-schema.org/draft-04/schema#", + title: "Undo an add-on rollout", + type: "object", + required: ["rolloutSlug"], + properties: { + rolloutSlug: { + description: "Unique identifer for the rollout to undo.", + type: "string", + pattern: "^[a-z0-9\\-_]+$", + }, + }, + }, + + "branched-addon-study": { + $schema: "http://json-schema.org/draft-04/schema#", + title: "Enroll a user in an add-on experiment, with managed branches", + type: "object", + required: [ + "slug", + "userFacingName", + "userFacingDescription", + "branches", + "isEnrollmentPaused", + ], + properties: { + slug: { + description: "Machine-readable identifier", + type: "string", + minLength: 1, + }, + userFacingName: { + description: "User-facing name of the study", + type: "string", + minLength: 1, + }, + userFacingDescription: { + description: "User-facing description of the study", + type: "string", + minLength: 1, + }, + isEnrollmentPaused: { + description: "If true, new users will not be enrolled in the study.", + type: "boolean", + default: true, + }, + branches: { + description: "List of experimental branches", + type: "array", + minItems: 1, + items: { + type: "object", + required: ["slug", "ratio", "extensionApiId"], + properties: { + slug: { + description: + "Unique identifier for this branch of the experiment.", + type: "string", + pattern: "^[A-Za-z0-9\\-_]+$", + }, + ratio: { + description: + "Ratio of users who should be grouped into this branch.", + type: "integer", + minimum: 1, + }, + extensionApiId: { + description: + "The record ID of the add-on uploaded to the Normandy server. May be null, in which case no add-on will be installed.", + type: ["number", "null"], + default: null, + }, + }, + }, + }, + }, + }, + + "show-heartbeat": { + $schema: "http://json-schema.org/draft-04/schema#", + title: "Show a Heartbeat survey.", + description: "This action shows a single survey.", + + type: "object", + required: [ + "surveyId", + "message", + "thanksMessage", + "postAnswerUrl", + "learnMoreMessage", + "learnMoreUrl", + ], + properties: { + repeatOption: { + type: "string", + enum: ["once", "xdays", "nag"], + description: "Determines how often a prompt is shown executes.", + default: "once", + }, + repeatEvery: { + description: + "For repeatOption=xdays, how often (in days) the prompt is displayed.", + default: null, + type: ["number", "null"], + }, + includeTelemetryUUID: { + type: "boolean", + description: "Include unique user ID in post-answer-url and Telemetry", + default: false, + }, + surveyId: { + type: "string", + description: "Slug uniquely identifying this survey in telemetry", + }, + message: { + description: "Message to show to the user", + type: "string", + }, + engagementButtonLabel: { + description: + "Text for the engagement button. If specified, this button will be shown instead of rating stars.", + default: null, + type: ["string", "null"], + }, + thanksMessage: { + description: + "Thanks message to show to the user after they've rated Firefox", + type: "string", + }, + postAnswerUrl: { + description: + "URL to redirect the user to after rating Firefox or clicking the engagement button", + default: null, + type: ["string", "null"], + }, + learnMoreMessage: { + description: "Message to show to the user to learn more", + default: null, + type: ["string", "null"], + }, + learnMoreUrl: { + description: "URL to show to the user when they click Learn More", + default: null, + type: ["string", "null"], + }, + }, + }, + + "multi-preference-experiment": { + $schema: "http://json-schema.org/draft-04/schema#", + title: "Run a feature experiment activated by a set of preferences.", + type: "object", + required: [ + "slug", + "userFacingName", + "userFacingDescription", + "branches", + "isEnrollmentPaused", + ], + properties: { + slug: { + description: "Unique identifier for this experiment", + type: "string", + pattern: "^[A-Za-z0-9\\-_]+$", + }, + userFacingName: { + description: "User-facing name of the experiment", + type: "string", + minLength: 1, + }, + userFacingDescription: { + description: "User-facing description of the experiment", + type: "string", + minLength: 1, + }, + experimentDocumentUrl: { + description: "URL of a document describing the experiment", + type: "string", + format: "uri", + default: "", + }, + isHighPopulation: { + description: + "Marks the preference experiment as a high population experiment, that should be excluded from certain types of telemetry", + type: "boolean", + default: "false", + }, + isEnrollmentPaused: { + description: "If true, new users will not be enrolled in the study.", + type: "boolean", + default: true, + }, + branches: { + description: "List of experimental branches", + type: "array", + minItems: 1, + items: { + type: "object", + required: ["slug", "ratio", "preferences"], + properties: { + slug: { + description: + "Unique identifier for this branch of the experiment", + type: "string", + pattern: "^[A-Za-z0-9\\-_]+$", + }, + ratio: { + description: + "Ratio of users who should be grouped into this branch", + type: "integer", + minimum: 1, + }, + preferences: { + description: + "The set of preferences to be set if this branch is chosen", + type: "object", + patternProperties: { + ".*": { + type: "object", + properties: { + preferenceType: { + description: + "Data type of the preference that controls this experiment", + type: "string", + enum: ["string", "integer", "boolean"], + }, + preferenceBranchType: { + description: + "Controls whether the default or user value of the preference is modified", + type: "string", + enum: ["user", "default"], + default: "default", + }, + preferenceValue: { + description: + "Value for this preference when this branch is chosen", + type: ["string", "number", "boolean"], + }, + }, + required: [ + "preferenceType", + "preferenceBranchType", + "preferenceValue", + ], + }, + }, + }, + }, + }, + }, + }, + }, + + "single-preference-experiment": { + $schema: "http://json-schema.org/draft-04/schema#", + title: "Run a feature experiment activated by a preference.", + type: "object", + required: [ + "slug", + "preferenceName", + "preferenceType", + "branches", + "isEnrollmentPaused", + ], + properties: { + slug: { + description: "Unique identifier for this experiment", + type: "string", + pattern: "^[A-Za-z0-9\\-_]+$", + }, + experimentDocumentUrl: { + description: "URL of a document describing the experiment", + type: "string", + format: "uri", + default: "", + }, + preferenceName: { + description: + "Full dotted-path of the preference that controls this experiment", + type: "string", + }, + preferenceType: { + description: + "Data type of the preference that controls this experiment", + type: "string", + enum: ["string", "integer", "boolean"], + }, + preferenceBranchType: { + description: + "Controls whether the default or user value of the preference is modified", + type: "string", + enum: ["user", "default"], + default: "default", + }, + isHighPopulation: { + description: + "Marks the preference experiment as a high population experiment, that should be excluded from certain types of telemetry", + type: "boolean", + default: "false", + }, + isEnrollmentPaused: { + description: "If true, new users will not be enrolled in the study.", + type: "boolean", + default: true, + }, + branches: { + description: "List of experimental branches", + type: "array", + minItems: 1, + items: { + type: "object", + required: ["slug", "value", "ratio"], + properties: { + slug: { + description: + "Unique identifier for this branch of the experiment", + type: "string", + pattern: "^[A-Za-z0-9\\-_]+$", + }, + value: { + description: "Value to set the preference to for this branch", + type: ["string", "number", "boolean"], + }, + ratio: { + description: + "Ratio of users who should be grouped into this branch", + type: "integer", + minimum: 1, + }, + }, + }, + }, + }, + }, +}; + +// Legacy name used on Normandy server +ActionSchemas["opt-out-study"] = ActionSchemas["addon-study"]; + +// If running in Node.js, export the schemas. +if (typeof module !== "undefined") { + /* globals module */ + module.exports = ActionSchemas; +} diff --git a/toolkit/components/normandy/actions/schemas/package.json b/toolkit/components/normandy/actions/schemas/package.json new file mode 100644 index 0000000000..f09031f88d --- /dev/null +++ b/toolkit/components/normandy/actions/schemas/package.json @@ -0,0 +1,11 @@ +{ + "name": "@mozilla/normandy-action-argument-schemas", + "version": "0.11.0", + "description": "Schemas for Normandy action arguments", + "main": "index.js", + "author": "Michael Cooper <mcooper@mozilla.com>", + "license": "MPL-2.0", + "scripts": { + "prepack": "node export_json.js" + } +} |