|
1 | 1 | #!/usr/bin/env python
|
| 2 | +# encoding: utf-8 |
2 | 3 |
|
3 | 4 | import argparse
|
4 | 5 | import subprocess
|
5 | 6 | import os
|
6 | 7 |
|
7 |
| -import package |
8 |
| -import sign |
| 8 | +import helpers |
| 9 | +from project import Project |
9 | 10 |
|
10 |
| -app = "GitX" |
11 |
| -product = "%s.app" % (app,) |
12 |
| -label = "dev" |
13 |
| -base_version = "0.15" |
14 |
| -release_branch = "master" |
15 | 11 |
|
16 |
| -signing_key = "Developer ID Application: Rowan James" |
| 12 | +def build(project): |
| 13 | + print "Building scheme {} ({}), please wait…".format(project.scheme(), project.current_config()) |
| 14 | + helpers.xcodebuild(project.scheme(), project.workspace(), project.current_build_config(), ["build"], project.build_base_dir()) |
| 15 | + print "Successfully built to {}".format(project.build_product()) |
17 | 16 |
|
18 |
| -project_root = os.getcwd() |
19 |
| -artifact_prefix = "%s-%s" % (app, label) |
20 |
| -workspace = "%s.xcworkspace" % (app,) |
21 |
| -scheme = "GitX" |
22 |
| -debug_config = "Debug" |
23 |
| -release_config = "Release" |
24 | 17 |
|
25 |
| -agvtool = "xcrun agvtool" |
| 18 | +def clean(project): |
| 19 | + print "Cleaning scheme {} ({})".format(project.scheme(), project.current_config()) |
| 20 | + helpers.xcodebuild(project.scheme(), project.workspace(), project.current_build_config(), ["clean"], project.build_base_dir()) |
26 | 21 |
|
27 |
| -updates_template_file = os.path.join(project_root, 'updates', 'GitX-dev.xml.tmpl') |
28 |
| -release_notes_file = os.path.join(project_root, 'updates', 'GitX-dev.html') |
29 |
| -updates_signing_key_file = os.path.join(project_root, 'updates', 'gitx-updates.key') |
30 |
| -updates_appcast_file = 'GitX-dev.xml' |
31 | 22 |
|
32 |
| -pause = 3 |
| 23 | +def build_cmd(args): |
| 24 | + if args.action == 'clean': |
| 25 | + project = Project(os.getcwd(), "debug") |
| 26 | + clean(project) |
| 27 | + project = Project(os.getcwd(), "release") |
| 28 | + clean(project) |
| 29 | + else: |
| 30 | + project = Project(os.getcwd(), args.action, None) |
| 31 | + build(project) |
33 | 32 |
|
34 |
| -build_base_dir = os.path.join(project_root, "build") |
35 |
| - |
36 |
| -class BuildError(RuntimeError): |
37 |
| - pass |
38 |
| - |
39 |
| -def clean(args): |
40 |
| - clean_scheme(scheme, args.config) |
41 |
| - |
42 |
| -def release(): |
43 |
| - try: |
44 |
| - assert_clean() |
45 |
| - assert_branch(release_branch) |
46 |
| - build_number = commit_count() |
47 |
| - set_versions(base_version, build_number, "dev") |
48 |
| - |
49 |
| - build_scheme(scheme, release_config) |
50 |
| - |
51 |
| - build_dir = os.path.join(build_base_dir, release_config) |
52 |
| - built_product = os.path.join(build_dir, product) |
53 |
| - sign_app(built_product) |
54 |
| - |
55 |
| - image_path = os.path.join(build_dir, "%s-%s.dmg" % (artifact_prefix, build_number)) |
56 |
| - image_name = "%s %s" % (app, build_number) |
57 |
| - package_app(built_product, image_path, image_name) |
58 |
| - |
59 |
| - prepare_release(build_number, image_path) |
60 |
| - |
61 |
| - except BuildError as e: |
62 |
| - print("error: %s" % (str(e),)) |
63 |
| - |
64 |
| - |
65 |
| -def debug(): |
66 |
| - try: |
67 |
| - build_scheme(scheme, debug_config) |
68 |
| - |
69 |
| - except BuildError as e: |
70 |
| - print("error: %s" % (str(e),)) |
71 |
| - |
72 |
| - |
73 |
| -def prepare_release(build_number, image_source_path): |
74 |
| - release_dir = "release" |
75 |
| - try: |
76 |
| - os.makedirs(release_dir) |
77 |
| - except OSError: |
78 |
| - pass |
79 |
| - |
80 |
| - # Tag the release |
81 |
| - tag = 'builds/%s/%s' % (base_version, build_number) |
82 |
| - subprocess.check_call(['git', 'tag', tag]) |
83 |
| - |
84 |
| - import appcast |
85 |
| - appcast_text = appcast.generate_appcast(image_source_path, updates_template_file, build_number, updates_signing_key_file) |
86 |
| - with open(os.path.join(release_dir, updates_appcast_file), 'w') as appcast_file: |
87 |
| - appcast_file.write(appcast_text) |
88 |
| - |
89 |
| - import shutil |
90 |
| - copied_image = os.path.join(release_dir, os.path.basename(image_source_path)) |
91 |
| - unversioned_image = os.path.join(release_dir, artifact_prefix + ".dmg") |
92 |
| - shutil.copyfile(image_source_path, copied_image) |
93 |
| - shutil.copyfile(image_source_path, unversioned_image) |
94 |
| - |
95 |
| - publish_release_notes_file = os.path.join(release_dir, os.path.basename(release_notes_file)) |
96 |
| - shutil.copyfile(release_notes_file, publish_release_notes_file) |
97 |
| - publish_release_notes_filebase, publish_release_notes_ext = os.path.splitext(publish_release_notes_file) |
98 |
| - publish_release_notes_version_file = "%s-%s%s" % (publish_release_notes_filebase, build_number, publish_release_notes_ext) |
99 |
| - shutil.copyfile(release_notes_file, publish_release_notes_version_file) |
100 |
| - |
101 |
| - |
102 |
| -def build(args): |
103 |
| - if args.config == "debug": |
104 |
| - debug() |
105 |
| - if args.config == "release": |
106 |
| - release() |
107 |
| - |
108 |
| - |
109 |
| -def assert_clean(): |
110 |
| - 0 |
111 |
| - # status = check_string_output(["git", "status", "--porcelain", "--untracked-files=no"]) |
112 |
| - # if len(status): |
113 |
| - # raise BuildError("Working copy must be clean\n%s" % status) |
114 |
| - |
115 |
| - |
116 |
| -def assert_branch(branch="master"): |
117 |
| - ref = check_string_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]) |
118 |
| - if ref != branch: |
119 |
| - raise BuildError("HEAD must be %s, but is %s" % (branch, ref)) |
120 |
| - |
121 |
| - |
122 |
| -def build_scheme(scheme, config): |
123 |
| - xcodebuild(scheme, workspace, config, ["build"]) |
124 |
| - |
125 |
| - |
126 |
| -def clean_scheme(scheme, config): |
127 |
| - xcodebuild(scheme, workspace, config, ["clean"]) |
128 |
| - |
129 |
| - |
130 |
| -def commit_count(): |
131 |
| - count = check_string_output(["git", "rev-list", "HEAD", "--count"]) |
132 |
| - return count |
133 |
| - |
134 |
| - |
135 |
| -def set_versions(base_version, build_number, label): |
136 |
| - print("mvers: " + check_string_output(["agvtool", "mvers", "-terse1"])) |
137 |
| - print("vers: " + check_string_output(["agvtool", "vers", "-terse"])) |
138 |
| - marketing_version = "%s.%s %s" % (base_version, build_number, label) |
139 |
| - build_version = "%s.%s" % (base_version, build_number) |
140 |
| - subprocess.check_call(["agvtool", "new-marketing-version", marketing_version]) |
141 |
| - subprocess.check_call(["agvtool", "new-version", "-all", build_version]) |
142 |
| - |
143 |
| - |
144 |
| -def xcodebuild(scheme, workspace, config, commands): |
145 |
| - cmd = ["xcrun", "xcodebuild", "-workspace", workspace, "-scheme", scheme, "-configuration", config] |
146 |
| - cmd = cmd + commands |
147 |
| - cmd.append('BUILD_DIR=%s' % (build_base_dir)) |
148 |
| - try: |
149 |
| - output = check_string_output(cmd) |
150 |
| - return output |
151 |
| - except subprocess.CalledProcessError as e: |
152 |
| - raise BuildError(str(e)) |
153 |
| - |
154 |
| - |
155 |
| -def check_string_output(command): |
156 |
| - return subprocess.check_output(command).decode('utf-8').strip() |
157 |
| - |
158 |
| - |
159 |
| -def sign_app(app_path): |
160 |
| - sign.sign_everything_in_app(app_path, key=signing_key) |
161 |
| - |
162 |
| - |
163 |
| -def package_app(app_path, image_path, image_name): |
164 |
| - package.package(app_path, image_path, image_name) |
165 | 33 |
|
166 | 34 | if __name__ == "__main__":
|
167 |
| - script_dir = os.path.dirname(os.path.abspath(__file__)) |
168 |
| - |
169 | 35 | parser = argparse.ArgumentParser()
|
170 |
| - subparsers = parser.add_subparsers() |
171 |
| - |
172 |
| - parser_config = subparsers.add_parser('config') |
173 |
| - parser_config.add_argument('config', choices=['debug', 'release']) |
174 |
| - parser_config.set_defaults(func=clean) |
175 |
| - |
176 |
| - parser_build = subparsers.add_parser('build') |
177 |
| - parser_build.add_argument('config', choices=['debug', 'release']) |
178 |
| - parser_build.set_defaults(func=build) |
| 36 | + parser.add_argument('action', choices=['debug', 'release', 'clean'], nargs='?', default='debug') |
| 37 | + parser.set_defaults(func=build_cmd) |
179 | 38 |
|
180 | 39 | args = parser.parse_args()
|
181 | 40 | args.func(args)
|
0 commit comments