ed2ab21f0fbe4939762468f08826e193aba59f9f
[platform/upstream/v8.git] / tools / release / auto_roll.py
1 #!/usr/bin/env python
2 # Copyright 2014 the V8 project authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import argparse
7 import json
8 import os
9 import sys
10 import urllib
11
12 from common_includes import *
13 import chromium_roll
14
15
16 class CheckActiveRoll(Step):
17   MESSAGE = "Check active roll."
18
19   @staticmethod
20   def ContainsChromiumRoll(changes):
21     for change in changes:
22       if change["subject"].startswith("Update V8 to"):
23         return True
24     return False
25
26   def RunStep(self):
27     params = {
28       "closed": 3,
29       "owner": self._options.author,
30       "limit": 30,
31       "format": "json",
32     }
33     params = urllib.urlencode(params)
34     search_url = "https://codereview.chromium.org/search"
35     result = self.ReadURL(search_url, params, wait_plan=[5, 20])
36     if self.ContainsChromiumRoll(json.loads(result)["results"]):
37       print "Stop due to existing Chromium roll."
38       return True
39
40
41 class DetectLastRoll(Step):
42   MESSAGE = "Detect commit ID of the last Chromium roll."
43
44   def RunStep(self):
45     # The revision that should be rolled. Check for the latest of the most
46     # recent releases based on commit timestamp.
47     revisions = self.GetRecentReleases(
48         max_age=self._options.max_age * DAY_IN_SECONDS)
49     assert revisions, "Didn't find any recent release."
50
51     # Update Chromium checkout before DEPS check to fix possible race-condition
52     self.GitPull(cwd=self._options.chromium)
53
54     # Interpret the DEPS file to retrieve the v8 revision.
55     # TODO(machenbach): This should be part or the roll-deps api of
56     # depot_tools.
57     Var = lambda var: '%s'
58     exec(FileToText(os.path.join(self._options.chromium, "DEPS")))
59
60     # The revision rolled last.
61     self["last_roll"] = vars['v8_revision']
62     last_version = self.GetVersionTag(self["last_roll"])
63     assert last_version, "The last rolled v8 revision is not tagged."
64
65     # There must be some progress between the last roll and the new candidate
66     # revision (i.e. we don't go backwards). The revisions are ordered newest
67     # to oldest. It is possible that the newest timestamp has no progress
68     # compared to the last roll, i.e. if the newest release is a cherry-pick
69     # on a release branch. Then we look further.
70     for revision in revisions:
71       version = self.GetVersionTag(revision)
72       assert version, "Internal error. All recent releases should have a tag"
73
74       if SortingKey(last_version) < SortingKey(version):
75         self["roll"] = revision
76         break
77     else:
78       print("There is no newer v8 revision than the one in Chromium (%s)."
79             % self["last_roll"])
80       return True
81
82
83 class RollChromium(Step):
84   MESSAGE = "Roll V8 into Chromium."
85
86   def RunStep(self):
87     if self._options.roll:
88       args = [
89         "--author", self._options.author,
90         "--reviewer", self._options.reviewer,
91         "--chromium", self._options.chromium,
92         "--last-roll", self["last_roll"],
93         "--use-commit-queue",
94         self["roll"],
95       ]
96       if self._options.sheriff:
97         args.append("--sheriff")
98       if self._options.dry_run:
99         args.append("--dry-run")
100       if self._options.work_dir:
101         args.extend(["--work-dir", self._options.work_dir])
102       self._side_effect_handler.Call(chromium_roll.ChromiumRoll().Run, args)
103
104
105 class AutoRoll(ScriptsBase):
106   def _PrepareOptions(self, parser):
107     parser.add_argument("-c", "--chromium", required=True,
108                         help=("The path to your Chromium src/ "
109                               "directory to automate the V8 roll."))
110     parser.add_argument("--max-age", default=3, type=int,
111                         help="Maximum age in days of the latest release.")
112     parser.add_argument("--roll", help="Call Chromium roll script.",
113                         default=False, action="store_true")
114
115   def _ProcessOptions(self, options):  # pragma: no cover
116     if not options.reviewer:
117       print "A reviewer (-r) is required."
118       return False
119     if not options.author:
120       print "An author (-a) is required."
121       return False
122     return True
123
124   def _Config(self):
125     return {
126       "PERSISTFILE_BASENAME": "/tmp/v8-auto-roll-tempfile",
127     }
128
129   def _Steps(self):
130     return [
131       CheckActiveRoll,
132       DetectLastRoll,
133       RollChromium,
134     ]
135
136
137 if __name__ == "__main__":  # pragma: no cover
138   sys.exit(AutoRoll().Run())