Add the support for scheduling a A/B testing with a patch.
[WebKit-https.git] / Websites / perf.webkit.org / public / api / update-triggerable.php
1 <?php
2
3 require_once('../include/json-header.php');
4 require_once('../include/repository-group-finder.php');
5
6 function main($post_data)
7 {
8     $db = new Database;
9     if (!$db->connect())
10         exit_with_error('DatabaseConnectionFailure');
11
12     $report = json_decode($post_data, true);
13     verify_slave($db, $report);
14
15     $triggerable_name = array_get($report, 'triggerable');
16     $triggerable = $db->select_first_row('build_triggerables', 'triggerable', array('name' => $triggerable_name));
17     if (!$triggerable)
18         exit_with_error('TriggerableNotFound', array('triggerable' => $triggerable_name));
19     $triggerable_id = $triggerable['triggerable_id'];
20
21     $configurations = array_get($report, 'configurations');
22     validate_configurations($db, $configurations);
23
24     $repository_groups = array_get($report, 'repositoryGroups', array());
25     validate_repository_groups($db, $repository_groups);
26
27     $finder = new RepositoryGroupFinder($db, $triggerable_id);
28     foreach ($repository_groups as &$group)
29         $group['existingGroup'] = $finder->find_by_repositories($group['repository_id_list']);
30
31     $db->begin_transaction();
32     if ($db->query_and_get_affected_rows('DELETE FROM triggerable_configurations WHERE trigconfig_triggerable = $1', array($triggerable_id)) === false) {
33         $db->rollback_transaction();
34         exit_with_error('FailedToDeleteExistingConfigurations', array('triggerable' => $triggerable_id));
35     }
36
37     foreach ($configurations as &$entry) {
38         $config_info = array('test' => $entry['test'], 'platform' => $entry['platform'], 'triggerable' => $triggerable_id);
39         if (!$db->insert_row('triggerable_configurations', 'trigconfig', $config_info, null)) {
40             $db->rollback_transaction();
41             exit_with_error('FailedToInsertConfiguration', array('entry' => $entry));
42         }
43     }
44
45     foreach ($repository_groups as &$group) {
46         $group_id = $group['existingGroup'];
47         $group_info = array(
48             'triggerable' => $triggerable_id,
49             'name' => $group['name'],
50             'description' => array_get($group, 'description'),
51             'accepts_roots' => Database::to_database_boolean(array_get($group, 'acceptsRoots', FALSE)));
52         if ($group_id) {
53             if (!$db->update_row('triggerable_repository_groups', 'repositorygroup', array('id' => $group_id), $group_info)) {
54                 $db->rollback_transaction();
55                 exit_with_error('FailedToInsertRepositoryGroup', array('repositoryGroup' => $group));
56             }
57         } else {
58             $group_id = $db->update_or_insert_row('triggerable_repository_groups', 'repositorygroup',
59                 array('triggerable' => $triggerable_id, 'name' => $group['name']), $group_info);
60             if (!$group_id) {
61                 $db->rollback_transaction();
62                 exit_with_error('FailedToInsertRepositoryGroup', array('repositoryGroup' => $group));
63             }
64         }
65         if ($db->query_and_get_affected_rows('DELETE FROM triggerable_repositories WHERE trigrepo_group = $1', array($group_id)) === FALSE) {
66             $db->rollback_transaction();
67             exit_with_error('FailedToDisassociateRepositories', array('repositoryGroup' => $group));
68         }
69         foreach ($group['repositories'] as $repository_data) {
70             $row = array('group' => $group_id,
71                 'repository' => $repository_data['repository'],
72                 'accepts_patch' => Database::to_database_boolean(array_get($repository_data, 'acceptsPatch', FALSE)));
73             if (!$db->insert_row('triggerable_repositories', 'trigrepo', $row, null)) {
74                 $db->rollback_transaction();
75                 exit_with_error('FailedToAssociateRepository', array('repositoryGroup' => $group, 'repository' => $repository_id));
76             }
77         }
78     }
79
80     $db->commit_transaction();
81     exit_with_success();
82 }
83
84 function validate_configurations($db, $configurations)
85 {
86     if (!is_array($configurations))
87         exit_with_error('InvalidConfigurations', array('configurations' => $configurations));
88
89     foreach ($configurations as $entry) {
90         if (!is_array($entry) || !array_key_exists('test', $entry) || !array_key_exists('platform', $entry))
91             exit_with_error('InvalidConfigurationEntry', array('configurationEntry' => $entry));
92     }
93 }
94
95 function validate_repository_groups($db, &$repository_groups)
96 {
97     if (!is_array($repository_groups))
98         exit_with_error('InvalidRepositoryGroups', array('repositoryGroups' => $repository_groups));
99
100     $top_level_repositories = $db->select_rows('repositories', 'repository', array('owner' => null));
101     $top_level_repository_ids = array();
102     foreach ($top_level_repositories as $repository_row)
103         $top_level_repository_ids[$repository_row['repository_id']] = true;
104
105     foreach ($repository_groups as &$group) {
106         if (!is_array($group) || !array_key_exists('name', $group) || !array_key_exists('repositories', $group) || !is_array($group['repositories']))
107             exit_with_error('InvalidRepositoryGroup', array('repositoryGroup' => $group));
108
109         $accepts_roots = array_get($group, 'acceptsRoots', FALSE);
110         if ($accepts_roots !== TRUE && $accepts_roots !== FALSE)
111             exit_with_error('InvalidAcceptsRoots', array('repositoryGroup' => $group, 'acceptsRoots' => accepts_roots));
112
113         $repository_list = $group['repositories'];
114         $group_repository_list = array();
115         foreach ($repository_list as $repository_data) {
116             if (!$repository_data || !is_array($repository_data))
117                 exit_with_error('InvalidRepositoryData', array('repositoryGroup' => $group, 'data' => $repository_data));
118
119             $id = array_get($repository_data, 'repository');
120             if (!$id || !is_numeric($id) || !array_key_exists($id, $top_level_repository_ids))
121                 exit_with_error('InvalidRepository', array('repositoryGroup' => $group, 'repository' => $id));
122
123             if (array_key_exists($id, $group_repository_list))
124                 exit_with_error('DuplicateRepository', array('repositoryGroup' => $group, 'repository' => $id));
125
126             $accepts_patch = array_get($repository_data, 'acceptsPatch', FALSE);
127             if ($accepts_patch !== TRUE && $accepts_patch !== FALSE)
128                 exit_with_error('InvalidRepositoryData', array('repositoryGroup' => $group, 'repository' => $id));
129
130             $group_repository_list[$id] = true;
131         }
132         $group['repository_id_list'] = array_keys($group_repository_list);
133     }
134 }
135
136 main($HTTP_RAW_POST_DATA);
137
138 ?>