https://bugs.webkit.org/show_bug.cgi?id=170228
Reviewed by Chris Dumez.
On some triggerable, it's desirable to specify multiple sets of repositories that are accepted.
For example, if a repository X transitioned from Subversion to Git, and if a triggerable accepted X and
some other repository Y, then it's desirable to two sets: (X-Subversion, Y) and (X-Git, Y) since neither
(X-Subversion, X-Git) nor (X-Subversion, X-Git, Y) makes sense as a set.
This patch introduces triggerable_repository_groups table to represent a set of repositories accepted by
a triggerable. It has many to one relationship to build_triggerables and triggerable_repositories in turn
now has many to one relationship to triggerable_repository_groups instead of build_triggerables.
Also make it possible to disable a triggerable e.g. a set of tests and platforms are no longer supported.
We don't want to delete the triggerable completely from the database since it would result in the associated
A/B testing results being purged, which is not desirale.
To migrate an existing database, run the following transaction:
```sql
BEGIN;
ALTER TABLE build_triggerables ADD COLUMN triggerable_disabled boolean NOT NULL DEFAULT FALSE;
CREATE TABLE triggerable_repository_groups (
repositorygroup_id serial PRIMARY KEY,
repositorygroup_triggerable integer REFERENCES build_triggerables NOT NULL,
repositorygroup_name varchar(256) NOT NULL,
repositorygroup_description varchar(256),
repositorygroup_accepts_roots boolean NOT NULL DEFAULT FALSE,
CONSTRAINT repository_group_name_must_be_unique_for_triggerable
UNIQUE(repositorygroup_triggerable, repositorygroup_name));
INSERT INTO triggerable_repository_groups (repositorygroup_triggerable, repositorygroup_name)
SELECT triggerable_id, 'default' FROM build_triggerables;
ALTER TABLE triggerable_repositories ADD COLUMN trigrepo_group integer REFERENCES triggerable_repository_groups;
UPDATE triggerable_repositories SET trigrepo_group = repositorygroup_id FROM triggerable_repository_groups
WHERE trigrepo_triggerable = repositorygroup_triggerable;
ALTER TABLE triggerable_repositories ALTER COLUMN trigrepo_group SET NOT NULL;
ALTER TABLE triggerable_repositories DROP COLUMN trigrepo_triggerable;
ALTER TABLE triggerable_repositories DROP COLUMN trigrepo_sub_roots;
END;
```
* init-database.sql:
* public/admin/triggerables.php: Use a custom column to make forms to add and configure repository groups.
(insert_triggerable_repositories): Added.
(generate_repository_list): Added.
(generate_repository_form): Added.
(generate_repository_checkboxes): Now generates checkboxes for a repository group instead of a triggerable.
* public/include/manifest-generator.php:
(fetch_triggerables): Fixed the bug that we were not filtering results with query in /api/triggerable.
Rewrote it to include an array of repository groups, which in turn contains an array of repositories along
with its name and a description, and a boolean indicating whether it accepts a custom root file or not.
The boolean will be used when we're adding the support for perf try bots. We will keep acceptedRepositories
since it's still used by detect-changes.js.
* public/v3/models/manifest.js:
(Manifest._didFetchManifest): Resolve repositoriy, test, and platform IDs to their respective objects.
* public/v3/models/triggerable.js:
(Triggerable):
(Triggerable.prototype.isDisabled): Added.
(Triggerable.prototype.repositoryGroups): Added.
(Triggerable.prototype.acceptsTest): Added.
(TriggerableRepositoryGroup): Added.
(TriggerableRepositoryGroup.prototype.description): Added.
(TriggerableRepositoryGroup.prototype.acceptsCustomRoots): Added.
(TriggerableRepositoryGroup.prototype.repositories): Added.
* public/v3/pages/analysis-task-page.js:
(AnalysisTaskPage.prototype._didFetchTask): Don't use a disabled triggerable.
* server-tests/api-manifest-tests.js: Updated a test case to test repository groups.
* tools/js/database.js:
(tableToPrefixMap): Added triggerable_repository_groups.
* tools/js/v3-models.js: Imported TriggerableRepositoryGroup from triggerable.js.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214975
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2017-04-05 Ryosuke Niwa <rniwa@webkit.org>
+
+ Introduce the notion of repository groups to triggerables
+ https://bugs.webkit.org/show_bug.cgi?id=170228
+
+ Reviewed by Chris Dumez.
+
+ On some triggerable, it's desirable to specify multiple sets of repositories that are accepted.
+
+ For example, if a repository X transitioned from Subversion to Git, and if a triggerable accepted X and
+ some other repository Y, then it's desirable to two sets: (X-Subversion, Y) and (X-Git, Y) since neither
+ (X-Subversion, X-Git) nor (X-Subversion, X-Git, Y) makes sense as a set.
+
+ This patch introduces triggerable_repository_groups table to represent a set of repositories accepted by
+ a triggerable. It has many to one relationship to build_triggerables and triggerable_repositories in turn
+ now has many to one relationship to triggerable_repository_groups instead of build_triggerables.
+
+ Also make it possible to disable a triggerable e.g. a set of tests and platforms are no longer supported.
+ We don't want to delete the triggerable completely from the database since it would result in the associated
+ A/B testing results being purged, which is not desirale.
+
+ To migrate an existing database, run the following transaction:
+ ```sql
+ BEGIN;
+ ALTER TABLE build_triggerables ADD COLUMN triggerable_disabled boolean NOT NULL DEFAULT FALSE;
+
+ CREATE TABLE triggerable_repository_groups (
+ repositorygroup_id serial PRIMARY KEY,
+ repositorygroup_triggerable integer REFERENCES build_triggerables NOT NULL,
+ repositorygroup_name varchar(256) NOT NULL,
+ repositorygroup_description varchar(256),
+ repositorygroup_accepts_roots boolean NOT NULL DEFAULT FALSE,
+ CONSTRAINT repository_group_name_must_be_unique_for_triggerable
+ UNIQUE(repositorygroup_triggerable, repositorygroup_name));
+ INSERT INTO triggerable_repository_groups (repositorygroup_triggerable, repositorygroup_name)
+ SELECT triggerable_id, 'default' FROM build_triggerables;
+
+ ALTER TABLE triggerable_repositories ADD COLUMN trigrepo_group integer REFERENCES triggerable_repository_groups;
+ UPDATE triggerable_repositories SET trigrepo_group = repositorygroup_id FROM triggerable_repository_groups
+ WHERE trigrepo_triggerable = repositorygroup_triggerable;
+ ALTER TABLE triggerable_repositories ALTER COLUMN trigrepo_group SET NOT NULL;
+
+ ALTER TABLE triggerable_repositories DROP COLUMN trigrepo_triggerable;
+ ALTER TABLE triggerable_repositories DROP COLUMN trigrepo_sub_roots;
+ END;
+ ```
+
+ * init-database.sql:
+ * public/admin/triggerables.php: Use a custom column to make forms to add and configure repository groups.
+ (insert_triggerable_repositories): Added.
+ (generate_repository_list): Added.
+ (generate_repository_form): Added.
+ (generate_repository_checkboxes): Now generates checkboxes for a repository group instead of a triggerable.
+
+ * public/include/manifest-generator.php:
+ (fetch_triggerables): Fixed the bug that we were not filtering results with query in /api/triggerable.
+ Rewrote it to include an array of repository groups, which in turn contains an array of repositories along
+ with its name and a description, and a boolean indicating whether it accepts a custom root file or not.
+ The boolean will be used when we're adding the support for perf try bots. We will keep acceptedRepositories
+ since it's still used by detect-changes.js.
+
+ * public/v3/models/manifest.js:
+ (Manifest._didFetchManifest): Resolve repositoriy, test, and platform IDs to their respective objects.
+
+ * public/v3/models/triggerable.js:
+ (Triggerable):
+ (Triggerable.prototype.isDisabled): Added.
+ (Triggerable.prototype.repositoryGroups): Added.
+ (Triggerable.prototype.acceptsTest): Added.
+ (TriggerableRepositoryGroup): Added.
+ (TriggerableRepositoryGroup.prototype.description): Added.
+ (TriggerableRepositoryGroup.prototype.acceptsCustomRoots): Added.
+ (TriggerableRepositoryGroup.prototype.repositories): Added.
+
+ * public/v3/pages/analysis-task-page.js:
+ (AnalysisTaskPage.prototype._didFetchTask): Don't use a disabled triggerable.
+
+ * server-tests/api-manifest-tests.js: Updated a test case to test repository groups.
+
+ * tools/js/database.js:
+ (tableToPrefixMap): Added triggerable_repository_groups.
+
+ * tools/js/v3-models.js: Imported TriggerableRepositoryGroup from triggerable.js.
+
2017-03-31 Ryosuke Niwa <rniwa@webkit.org>
Build fix. For OS versions, we can end up with non-alphanumeric revision.
DROP TYPE IF EXISTS analysis_task_result_type CASCADE;
DROP TABLE IF EXISTS build_triggerables CASCADE;
DROP TABLE IF EXISTS triggerable_configurations CASCADE;
+DROP TABLE IF EXISTS triggerable_repository_groups CASCADE;
DROP TABLE IF EXISTS triggerable_repositories CASCADE;
DROP TABLE IF EXISTS uploaded_files CASCADE;
DROP TABLE IF EXISTS bugs CASCADE;
CREATE TABLE build_triggerables (
triggerable_id serial PRIMARY KEY,
- triggerable_name varchar(64) NOT NULL UNIQUE);
+ triggerable_name varchar(64) NOT NULL UNIQUE,
+ triggerable_disabled boolean NOT NULL DEFAULT FALSE);
+
+CREATE TABLE triggerable_repository_groups (
+ repositorygroup_id serial PRIMARY KEY,
+ repositorygroup_triggerable integer REFERENCES build_triggerables NOT NULL,
+ repositorygroup_name varchar(256) NOT NULL,
+ repositorygroup_description varchar(256),
+ repositorygroup_accepts_roots boolean NOT NULL DEFAULT FALSE,
+ CONSTRAINT repository_group_name_must_be_unique_for_triggerable UNIQUE(repositorygroup_triggerable, repositorygroup_name));
CREATE TABLE triggerable_repositories (
- trigrepo_triggerable integer REFERENCES build_triggerables NOT NULL,
trigrepo_repository integer REFERENCES repositories NOT NULL,
- trigrepo_sub_roots boolean NOT NULL DEFAULT FALSE);
+ trigrepo_group integer REFERENCES triggerable_repository_groups NOT NULL);
CREATE TABLE triggerable_configurations (
trigconfig_test integer REFERENCES tests NOT NULL,
} else if ($action == 'update') {
if (update_field('build_triggerables', 'triggerable', 'name'))
regenerate_manifest();
+ else if (update_field('build_triggerables', 'triggerable', 'disabled', Database::to_database_boolean(array_get($_POST, 'disabled'))))
+ regenerate_manifest();
else
notice('Invalid parameters.');
+ } else if ($action == 'update-group-name') {
+ if (update_field('triggerable_repository_groups', 'repositorygroup', 'name'))
+ regenerate_manifest();
+ } else if ($action == 'update-group-description') {
+ if (update_field('triggerable_repository_groups', 'repositorygroup', 'description'))
+ regenerate_manifest();
+ } else if ($action == 'update-group-accept-roots') {
+ if (update_field('triggerable_repository_groups', 'repositorygroup', 'accepts_roots',
+ Database::to_database_boolean(array_get($_POST, 'accepts'))))
+ regenerate_manifest();
+ } else if ($action == 'update-repository') {
+ $association = array_get($_POST, 'association');
+ $triggerable_id = array_get($_POST, 'triggerable');
+ $repository_id = array_get($_POST, 'repository');
+
+ $should_delete = FALSE;
+ $accepted = $association == 'accepted';
+ $required = $association == 'required';
+ if ($accepted || $required) {
+ $db->begin_transaction();
+ $select = array('repository' => $repository_id, 'triggerable' => $triggerable_id);
+ $update = array('repository' => $repository_id, 'triggerable' => $triggerable_id, 'required' => Database::to_database_boolean($required));
+ if (!$db->update_row('triggerable_repositories', 'trigrepo', $select, $update, 'repository')) {
+ notice("Failed to update the association of repository $repository_id with triggerable $triggerable_id.");
+ $db->rollback_transaction();
+ } else
+ $db->commit_transaction();
+ } else if ($association == 'not-accepted') {
+ $db->begin_transaction();
+ $result = $db->query_and_get_affected_rows("DELETE FROM triggerable_repositories WHERE trigrepo_triggerable = $1 AND trigrepo_repository = $2",
+ array($triggerable_id, $repository_id));
+ if ($result > 1) {
+ notice("Failed to update the association of repository $repository_id with triggerable $triggerable_id.");
+ $db->rollback_transaction();
+ } else
+ $db->commit_transaction();
+ }
} else if ($action == 'update-repositories') {
- $triggerable_id = intval($_POST['id']);
+ $group_id = intval($_POST['group']);
$db->begin_transaction();
- $db->query_and_get_affected_rows("DELETE FROM triggerable_repositories WHERE trigrepo_triggerable = $1", array($triggerable_id));
-
- $repositories = array_get($_POST, 'repositories');
- $suceeded = TRUE;
- if ($repositories) {
- foreach ($repositories as $repository_id) {
- if (!$db->insert_row('triggerable_repositories', 'trigrepo', array('triggerable' => $triggerable_id, 'repository' => $repository_id), NULL)) {
- $suceeded = FALSE;
- notice("Failed to associate repository $repository_id with triggerable $triggerable_id.");
- break;
- }
- }
- }
+ $db->query_and_get_affected_rows("DELETE FROM triggerable_repositories WHERE trigrepo_group = $1", array($group_id));
+ $suceeded = insert_triggerable_repositories($db, $group_id, array_get($_POST, 'repositories'));
if ($suceeded) {
$db->commit_transaction();
notice('Updated the association.');
regenerate_manifest();
} else
$db->rollback_transaction();
+ } else if ($action == 'add-repository-group') {
+ $triggerable_id = intval($_POST['triggerable']);
+ $name = $_POST['name'];
+
+ $db->begin_transaction();
+ $group_id = $db->insert_row('triggerable_repository_groups', 'repositorygroup', array('name' => $name, 'triggerable' => $triggerable_id));
+ if (!$group_id)
+ notice('Failed to insert the specified repository group.');
+ else if (!insert_triggerable_repositories($db, $group_id, array_get($_POST, 'repositories')))
+ $db->rollback_transaction();
+ else {
+ $db->commit_transaction();
+ notice('Updated the association.');
+ regenerate_manifest();
+ }
}
$repository_rows = $db->fetch_table('repositories', 'repository_name');
- $repository_names = array();
-
$page = new AdministrativePage($db, 'build_triggerables', 'triggerable', array(
'name' => array('editing_mode' => 'string'),
- 'repositories' => array('custom' => function ($triggerable_row) use (&$repository_rows) {
- return array(generate_repository_checkboxes($triggerable_row['triggerable_id'], $repository_rows));
- }),
+ 'disabled' => array('editing_mode' => 'boolean', 'post_insertion' => TRUE),
+ 'repositories' => array(
+ 'label' => 'Repository Groups',
+ 'subcolumns'=> array('ID', 'Name', 'Description', 'Accepts Roots', 'Repositories'),
+ 'custom' => function ($triggerable_row) use (&$db, &$repository_rows) {
+ return generate_repository_list($db, $triggerable_row['triggerable_id'], $repository_rows);
+ }),
));
- function generate_repository_checkboxes($triggerable_id, $repository_rows) {
- global $db;
+ $page->render_table('name');
+ $page->render_form_to_add();
+}
+
+function insert_triggerable_repositories($db, $group_id, $repositories)
+{
+ if (!$repositories)
+ return TRUE;
+ foreach ($repositories as $repository_id) {
+ if (!$db->insert_row('triggerable_repositories', 'trigrepo', array('group' => $group_id, 'repository' => $repository_id), NULL)) {
+ notice("Failed to associate repository $repository_id with repository group $group_id.");
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
- $repository_rows = $db->query_and_fetch_all('SELECT * FROM repositories LEFT OUTER JOIN triggerable_repositories
- ON trigrepo_repository = repository_id AND trigrepo_triggerable = $1 ORDER BY repository_name', array($triggerable_id));
+function generate_repository_list($db, $triggerable_id, $repository_rows) {
+ $group_forms = array();
- $form = <<< END
-<form method="POST">
-<input type="hidden" name="id" value="$triggerable_id">
-<input type="hidden" name="action" value="update-repositories">
+ $repository_groups = $db->select_rows('triggerable_repository_groups', 'repositorygroup', array('triggerable' => $triggerable_id), 'name');
+ foreach ($repository_groups as $group_row) {
+ $group_id = $group_row['repositorygroup_id'];
+ $group_name = $group_row['repositorygroup_name'];
+ $group_description = $group_row['repositorygroup_description'];
+ $checked_if_accepts_roots = Database::is_true($group_row['repositorygroup_accepts_roots']) ? 'checked' : '';
+
+ $group_name_form = <<< END
+ <form method="POST">
+ <input type="hidden" name="action" value="update-group-name">
+ <input type="hidden" name="id" value="$group_id">
+ <input type="text" name="name" value="$group_name">
+ </form>
END;
- foreach ($repository_rows as $row) {
- $checked = $row['trigrepo_triggerable'] ? ' checked' : '';
- $form .= <<< END
-<label><input type="checkbox" name="repositories[]" value="{$row['repository_id']}"$checked>{$row['repository_name']}</label>
+ $group_description_form = <<< END
+ <form method="POST">
+ <input type="hidden" name="action" value="update-group-description">
+ <input type="hidden" name="id" value="$group_id">
+ <input name="description" value="$group_description">
+ </form>
END;
- }
- return $form . <<< END
-<button>Save</button>
-</form>
+ $group_accepts_roots = <<< END
+ <form method="POST">
+ <input type="hidden" name="action" value="update-group-accept-roots">
+ <input type="hidden" name="id" value="$group_id">
+ <input type="checkbox" name="accepts" $checked_if_accepts_roots>
+ <button type="submit">Save</button>
+ </form>
END;
+
+ array_push($group_forms, array($group_id, $group_name_form, $group_description_form, $group_accepts_roots, generate_repository_form($db, $repository_rows, $group_id)));
}
- $page->render_table('name');
- $page->render_form_to_add();
+ $new_group_checkboxes = generate_repository_checkboxes($db, $repository_rows);
+ $new_group_form = <<< END
+ <form method="POST">
+ <input type="hidden" name="action" value="add-repository-group">
+ <input type="hidden" name="triggerable" value="$triggerable_id">
+ <input type="text" name="name" value="" required><br>
+ $new_group_checkboxes
+ <br><button type="submit">Add</button></form>
+END;
+
+ array_push($group_forms, $new_group_form);
+
+ return $group_forms;
+}
+
+function generate_repository_form($db, $repository_rows, $group_id)
+{
+ $checkboxes = generate_repository_checkboxes($db, $repository_rows, $group_id);
+ return <<< END
+ <form method="POST">
+ <input type="hidden" name="action" value="update-repositories">
+ <input type="hidden" name="group" value="$group_id">
+ $checkboxes
+ <br><button type="submit">Save</button></form>
+END;
+}
+
+function generate_repository_checkboxes($db, $repository_rows, $group_id = NULL)
+{
+ $repositories_in_group = array();
+ if ($group_id) {
+ $group_repository_rows = $db->select_rows('triggerable_repositories', 'trigrepo', array('group' => $group_id));
+ foreach ($group_repository_rows as $row)
+ $repositories_in_group[$row['trigrepo_repository']] = TRUE;
+ }
+
+ $form = '';
+ foreach ($repository_rows as $row) {
+ $id = $row['repository_id'];
+ $name = $row['repository_name'];
+ $checked = array_key_exists($id, $repositories_in_group) ? 'checked' : '';
+ $form .= "<label><input type=\"checkbox\" name=\"repositories[]\" value=\"$id\" $checked>$name</label>";
+ }
+ return $form;
}
require('../include/admin-footer.php');
static function fetch_triggerables($db, $query)
{
- $triggerables = $db->fetch_table('build_triggerables');
+ $triggerables = $db->select_rows('build_triggerables', 'triggerable', $query);
if (!$triggerables)
return array();
$id_to_triggerable = array();
- foreach ($triggerables as $row) {
+ $triggerable_id_to_repository_set = array();
+ foreach ($triggerables as &$row) {
$id = $row['triggerable_id'];
$id_to_triggerable[$id] = array(
- 'id' => $id,
'name' => $row['triggerable_name'],
+ 'isDisabled' => Database::is_true($row['triggerable_disabled']),
'acceptedRepositories' => array(),
+ 'repositoryGroups' => array(),
'configurations' => array());
+ $triggerable_id_to_repository_set[$id] = array();
}
- $repository_map = $db->fetch_table('triggerable_repositories');
- if ($repository_map) {
- foreach ($repository_map as $row) {
- $triggerable = &$id_to_triggerable[$row['trigrepo_triggerable']];
- array_push($triggerable['acceptedRepositories'], $row['trigrepo_repository']);
+ $repository_groups = $db->fetch_table('triggerable_repository_groups', 'repositorygroup_name');
+ $group_repositories = $db->fetch_table('triggerable_repositories');
+ if ($repository_groups && $group_repositories) {
+ $repository_set_by_group = array();
+ foreach ($group_repositories as &$repository_row) {
+ $group_id = $repository_row['trigrepo_group'];
+ array_ensure_item_has_array($repository_set_by_group, $group_id);
+ array_push($repository_set_by_group[$group_id], $repository_row['trigrepo_repository']);
+ }
+ foreach ($repository_groups as &$group_row) {
+ $triggerable_id = $group_row['repositorygroup_triggerable'];
+ if (!array_key_exists($triggerable_id, $id_to_triggerable))
+ continue;
+ $triggerable = &$id_to_triggerable[$triggerable_id];
+ $group_id = $group_row['repositorygroup_id'];
+ $repository_list = array_get($repository_set_by_group, $group_id, array());
+ array_push($triggerable['repositoryGroups'], array(
+ 'id' => $group_row['repositorygroup_id'],
+ 'name' => $group_row['repositorygroup_name'],
+ 'description' => $group_row['repositorygroup_description'],
+ 'acceptsCustomRoots' => Database::is_true($group_row['repositorygroup_accepts_roots']),
+ 'repositories' => $repository_list));
+ // V2 UI compatibility.
+ foreach ($repository_list as $repository_id) {
+ $set = &$triggerable_id_to_repository_set[$triggerable_id];
+ if (array_key_exists($repository_id, $set))
+ continue;
+ $set[$repository_id] = true;
+ array_push($triggerable['acceptedRepositories'], $repository_id);
+ }
+
}
}
$configuration_map = $db->fetch_table('triggerable_configurations');
if ($configuration_map) {
- foreach ($configuration_map as $row) {
- $triggerable = &$id_to_triggerable[$row['trigconfig_triggerable']];
+ foreach ($configuration_map as &$row) {
+ $triggerable_id = $row['trigconfig_triggerable'];
+ if (!array_key_exists($triggerable_id, $id_to_triggerable))
+ continue;
+ $triggerable = &$id_to_triggerable[$triggerable_id];
array_push($triggerable['configurations'], array($row['trigconfig_test'], $row['trigconfig_platform']));
}
}
raw.acceptedRepositories = raw.acceptedRepositories.map((repositoryId) => {
return Repository.findById(repositoryId);
});
+ raw.repositoryGroups = raw.repositoryGroups.map((group) => {
+ group.repositories = group.repositories.map((repositoryId) => Repository.findById(repositoryId));
+ return TriggerableRepositoryGroup.ensureSingleton(group.id, group);
+ });
+ raw.configurations = raw.configurations.map((configuration) => {
+ const [testId, platformId] = configuration;
+ return {test: Test.findById(testId), platform: Platform.findById(platformId)};
+ });
});
Instrumentation.endMeasuringTime('Manifest', '_didFetchManifest');
{
super(id, object);
this._name = object.name;
+ this._isDisabled = !!object.isDisabled;
this._acceptedRepositories = object.acceptedRepositories;
+ this._repositoryGroups = object.repositoryGroups;
this._configurationList = object.configurations;
+ this._acceptedTests = new Set;
- let configurationMap = this.ensureNamedStaticMap('testConfigurations');
+ const configurationMap = this.ensureNamedStaticMap('testConfigurations');
for (const config of object.configurations) {
- const [testId, platformId] = config;
- const key = `${testId}-${platformId}`;
+ const key = `${config.test.id()}-${config.platform.id()}`;
+ this._acceptedTests.add(config.test);
console.assert(!(key in configurationMap));
configurationMap[key] = this;
}
}
+ isDisabled() { return this._isDisabled; }
acceptedRepositories() { return this._acceptedRepositories; }
+ repositoryGroups() { return this._repositoryGroups; }
+
+ acceptsTest(test) { return this._acceptedTests.has(test); }
static findByTestConfiguration(test, platform)
{
}
return null;
}
+}
+class TriggerableRepositoryGroup extends LabeledObject {
+
+ constructor(id, object)
+ {
+ super(id, object);
+ this._description = object.description;
+ this._acceptsCustomRoots = !!object.acceptsCustomRoots;
+ this._repositories = object.repositories;
+ }
+
+ description() { return this._description || this.name(); }
+ acceptsCustomRoots() { return this._acceptsCustomRoots; }
+ repositories() { return this._repositories; }
}
-if (typeof module != 'undefined')
+if (typeof module != 'undefined') {
module.exports.Triggerable = Triggerable;
+ module.exports.TriggerableRepositoryGroup = TriggerableRepositoryGroup;
+}
+
const platform = task.platform();
const metric = task.metric();
const lastModified = platform.lastModified(metric);
- this._triggerable = Triggerable.findByTestConfiguration(metric.test(), platform);
+ const triggerable = Triggerable.findByTestConfiguration(metric.test(), platform);
+ this._triggerable = triggerable && !triggerable.isDisabled() ? triggerable : null;
this._metric = metric;
this._measurementSet = MeasurementSet.findSet(platform.id(), metric.id(), lastModified);
db.insert('repositories', {id: 101, name: 'WebKit', owner: 9, url: 'https://trac.webkit.org/$1'}),
db.insert('build_triggerables', {id: 200, name: 'build.webkit.org'}),
db.insert('build_triggerables', {id: 201, name: 'ios-build.webkit.org'}),
+ db.insert('build_triggerables', {id: 202, name: 'mac-build.webkit.org', disabled: true}),
db.insert('tests', {id: 1, name: 'SomeTest'}),
db.insert('tests', {id: 2, name: 'SomeOtherTest'}),
db.insert('tests', {id: 3, name: 'ChildTest', parent: 1}),
db.insert('platforms', {id: 23, name: 'iOS 9 iPhone 5s'}),
db.insert('platforms', {id: 46, name: 'Trunk Mavericks'}),
+ db.insert('platforms', {id: 104, name: 'Trunk Sierra MacBookPro11,2'}),
db.insert('test_metrics', {id: 5, test: 1, name: 'Time'}),
db.insert('test_metrics', {id: 8, test: 2, name: 'FrameRate'}),
db.insert('test_metrics', {id: 9, test: 3, name: 'Time'}),
db.insert('test_configurations', {id: 104, metric: 5, platform: 23, type: 'current'}),
db.insert('test_configurations', {id: 105, metric: 8, platform: 23, type: 'current'}),
db.insert('test_configurations', {id: 106, metric: 9, platform: 23, type: 'current'}),
- db.insert('triggerable_repositories', {triggerable: 200, repository: 11}),
- db.insert('triggerable_repositories', {triggerable: 201, repository: 11}),
+ db.insert('test_configurations', {id: 107, metric: 5, platform: 104, type: 'current'}),
+ db.insert('test_configurations', {id: 108, metric: 8, platform: 104, type: 'current'}),
+ db.insert('test_configurations', {id: 109, metric: 9, platform: 104, type: 'current'}),
+ db.insert('triggerable_repository_groups', {id: 300, triggerable: 200, name: 'default'}),
+ db.insert('triggerable_repository_groups', {id: 301, triggerable: 201, name: 'default'}),
+ db.insert('triggerable_repository_groups', {id: 302, triggerable: 202, name: 'system-and-webkit'}),
+ db.insert('triggerable_repository_groups', {id: 312, triggerable: 202, name: 'system-and-roots', accepts_roots: true}),
+ db.insert('triggerable_repositories', {group: 300, repository: 11}),
+ db.insert('triggerable_repositories', {group: 301, repository: 11}),
+ db.insert('triggerable_repositories', {group: 302, repository: 11}),
+ db.insert('triggerable_repositories', {group: 302, repository: 9}),
+ db.insert('triggerable_repositories', {group: 312, repository: 9}),
db.insert('triggerable_configurations', {triggerable: 200, test: 1, platform: 46}),
db.insert('triggerable_configurations', {triggerable: 200, test: 2, platform: 46}),
db.insert('triggerable_configurations', {triggerable: 201, test: 1, platform: 23}),
db.insert('triggerable_configurations', {triggerable: 201, test: 2, platform: 23}),
+ db.insert('triggerable_configurations', {triggerable: 202, test: 1, platform: 104}),
+ db.insert('triggerable_configurations', {triggerable: 202, test: 2, platform: 104}),
]).then(() => {
return Manifest.fetch();
}).then(() => {
- let webkit = Repository.findById(11);
+ const webkit = Repository.findById(11);
assert.equal(webkit.name(), 'WebKit');
assert.equal(webkit.urlForRevision(123), 'https://trac.webkit.org/123');
- let osWebkit1 = Repository.findById(101);
+ const osWebkit1 = Repository.findById(101);
assert.equal(osWebkit1.name(), 'WebKit');
assert.equal(osWebkit1.owner(), 9);
assert.equal(osWebkit1.urlForRevision(123), 'https://trac.webkit.org/123');
- let osx = Repository.findById(9);
+ const osx = Repository.findById(9);
assert.equal(osx.name(), 'OS X');
- let someTest = Test.findById(1);
+ const someTest = Test.findById(1);
assert.equal(someTest.name(), 'SomeTest');
- let someOtherTest = Test.findById(2);
+ const someOtherTest = Test.findById(2);
assert.equal(someOtherTest.name(), 'SomeOtherTest');
- let childTest = Test.findById(3);
+ const childTest = Test.findById(3);
assert.equal(childTest.name(), 'ChildTest');
- let ios9iphone5s = Platform.findById(23);
+ const ios9iphone5s = Platform.findById(23);
assert.equal(ios9iphone5s.name(), 'iOS 9 iPhone 5s');
- let mavericks = Platform.findById(46);
+ const mavericks = Platform.findById(46);
assert.equal(mavericks.name(), 'Trunk Mavericks');
- assert.equal(Triggerable.all().length, 2);
+ const sierra = Platform.findById(104);
+ assert.equal(sierra.name(), 'Trunk Sierra MacBookPro11,2');
- let osxTriggerable = Triggerable.findByTestConfiguration(someTest, mavericks);
+ assert.equal(Triggerable.all().length, 3);
+
+ const osxTriggerable = Triggerable.findByTestConfiguration(someTest, mavericks);
assert.equal(osxTriggerable.name(), 'build.webkit.org');
assert.deepEqual(osxTriggerable.acceptedRepositories(), [webkit]);
assert.equal(Triggerable.findByTestConfiguration(someOtherTest, mavericks), osxTriggerable);
assert.equal(Triggerable.findByTestConfiguration(childTest, mavericks), osxTriggerable);
- let iosTriggerable = Triggerable.findByTestConfiguration(someOtherTest, ios9iphone5s);
+ const iosTriggerable = Triggerable.findByTestConfiguration(someOtherTest, ios9iphone5s);
assert.notEqual(iosTriggerable, osxTriggerable);
assert.equal(iosTriggerable.name(), 'ios-build.webkit.org');
assert.deepEqual(iosTriggerable.acceptedRepositories(), [webkit]);
assert.equal(Triggerable.findByTestConfiguration(someOtherTest, ios9iphone5s), iosTriggerable);
assert.equal(Triggerable.findByTestConfiguration(childTest, ios9iphone5s), iosTriggerable);
+
+ const macTriggerable = Triggerable.findByTestConfiguration(someTest, sierra);
+ assert.equal(macTriggerable.name(), 'mac-build.webkit.org');
+ assert.deepEqual(Repository.sortByName(macTriggerable.acceptedRepositories()), [osx, webkit]);
+ assert(macTriggerable.acceptsTest(someTest));
+
+ const groups = macTriggerable.repositoryGroups();
+ assert.deepEqual(groups.length, 2);
+ TriggerableRepositoryGroup.sortByName(groups);
+
+ assert.equal(groups[0].name(), 'system-and-roots');
+ assert.equal(groups[0].acceptsCustomRoots(), true);
+ assert.deepEqual(Repository.sortByName(groups[0].repositories()), [osx]);
+
+ assert.equal(groups[1].name(), 'system-and-webkit');
+ assert.equal(groups[1].acceptsCustomRoots(), false);
+ assert.deepEqual(Repository.sortByName(groups[1].repositories()), [osx, webkit]);
+
});
});
'tests': 'test',
'tracker_repositories': 'tracrepo',
'triggerable_configurations': 'trigconfig',
+ 'triggerable_repository_groups': 'repositorygroup',
'triggerable_repositories': 'trigrepo',
'platforms': 'platform',
'reports': 'report',
importFromV3('models/test-group.js', 'TestGroup');
importFromV3('models/time-series.js', 'TimeSeries');
importFromV3('models/triggerable.js', 'Triggerable');
+importFromV3('models/triggerable.js', 'TriggerableRepositoryGroup');
importFromV3('models/uploaded-file.js', 'UploadedFile');
importFromV3('privileged-api.js', 'PrivilegedAPI');