[M73 Dev][EFL] Fix errors to generate ninja files
[platform/framework/web/chromium-efl.git] / build / compute_build_timestamp.py
1 #!/usr/bin/env python
2 # Copyright 2018 The Chromium 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 """Returns a timestamp that approximates the build date.
6
7 build_type impacts the timestamp generated, both relative to the date of the
8 last recent commit:
9 - default: the build date is set to the most recent first Sunday of a month at
10   5:00am. The reason is that it is a time where invalidating the build cache
11   shouldn't have major reprecussions (due to lower load).
12 - official: the build date is set to the current date at 5:00am, or the day
13   before if the current time is before 5:00am.
14 Either way, it is guaranteed to be in the past and always in UTC.
15 """
16
17 # The requirements for the timestamp:
18 # (1) for the purposes of continuous integration, longer duration
19 #     between cache invalidation is better, but >=1mo is preferable.
20 # (2) for security purposes, timebombs would ideally be as close to
21 #     the actual time of the build as possible. It must be in the past.
22 # (3) HSTS certificate pinning is valid for 70 days. To make CI builds enforce
23 #     HTST pinning, <=1mo is preferable.
24 #
25 # On Windows, the timestamp is also written in the PE/COFF file header of
26 # executables of dlls.  That timestamp and the executable's file size are
27 # the only two pieces of information that identify a given executable on
28 # the symbol server, so rarely changing timestamps can cause conflicts there
29 # as well. We only upload symbols for official builds to the symbol server.
30
31 import argparse
32 import calendar
33 import datetime
34 import doctest
35 import os
36 import sys
37
38
39 THIS_DIR = os.path.abspath(os.path.dirname(__file__))
40
41
42 def GetFirstSundayOfMonth(year, month):
43   """Returns the first sunday of the given month of the given year.
44
45   >>> GetFirstSundayOfMonth(2016, 2)
46   7
47   >>> GetFirstSundayOfMonth(2016, 3)
48   6
49   >>> GetFirstSundayOfMonth(2000, 1)
50   2
51   """
52   weeks = calendar.Calendar().monthdays2calendar(year, month)
53   # Return the first day in the first week that is a Sunday.
54   return [date_day[0] for date_day in weeks[0] if date_day[1] == 6][0]
55
56
57 def GetBuildDate(build_type, utc_now):
58   """Gets the approximate build date given the specific build type.
59
60   >>> GetBuildDate('default', datetime.datetime(2016, 2, 6, 1, 2, 3))
61   datetime.datetime(2016, 1, 3, 1, 2, 3)
62   >>> GetBuildDate('default', datetime.datetime(2016, 2, 7, 5))
63   datetime.datetime(2016, 2, 7, 5, 0)
64   >>> GetBuildDate('default', datetime.datetime(2016, 2, 8, 5))
65   datetime.datetime(2016, 2, 7, 5, 0)
66   >>> GetBuildDate('official', datetime.datetime(2016, 2, 8, 5))
67   datetime.datetime(2016, 2, 8, 5, 0)
68   """
69   day = utc_now.day
70   month = utc_now.month
71   year = utc_now.year
72   if build_type != 'official':
73     first_sunday = GetFirstSundayOfMonth(year, month)
74     # If our build is after the first Sunday, we've already refreshed our build
75     # cache on a quiet day, so just use that day.
76     # Otherwise, take the first Sunday of the previous month.
77     if day >= first_sunday:
78       day = first_sunday
79     else:
80       month -= 1
81       if month == 0:
82         month = 12
83         year -= 1
84       day = GetFirstSundayOfMonth(year, month)
85   return datetime.datetime(
86       year, month, day, utc_now.hour, utc_now.minute, utc_now.second)
87
88
89 def main():
90   if doctest.testmod()[0]:
91     return 1
92   argument_parser = argparse.ArgumentParser()
93   argument_parser.add_argument(
94       'build_type', help='The type of build', choices=('official', 'default'))
95   args = argument_parser.parse_args()
96
97   # The mtime of the revision in build/util/LASTCHANGE is stored in a file
98   # next to it. Read it, to get a deterministic time close to "now".
99   # That date is then modified as described at the top of the file so that
100   # it changes less frequently than with every commit.
101   # This intentionally always uses build/util/LASTCHANGE's commit time even if
102   # use_dummy_lastchange is set.
103   lastchange_file = os.path.join(THIS_DIR, 'util', 'LASTCHANGE.committime')
104   last_commit_timestamp = int(open(lastchange_file).read())
105   now = datetime.datetime.utcfromtimestamp(last_commit_timestamp)
106
107   if now.hour < 5:
108     # The time is locked at 5:00 am in UTC to cause the build cache
109     # invalidation to not happen exactly at midnight. Use the same calculation
110     # as the day before.
111     # See //base/build_time.cc.
112     now = now - datetime.timedelta(days=1)
113   now = datetime.datetime(now.year, now.month, now.day, 5, 0, 0)
114   build_date = GetBuildDate(args.build_type, now)
115   print int(calendar.timegm(build_date.utctimetuple()))
116   return 0
117
118
119 if __name__ == '__main__':
120   sys.exit(main())