3 # Copyright 2014 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
7 '''Publishes a set of extensions to the webstore.
8 Given an unpacked extension, compresses and sends to the Chrome webstore.
10 Releasing to the webstore should involve the following manual steps before
12 1. clean the output directory.
13 2. make a release build.
14 3. run manual smoke tests.
15 4. run automated tests.
18 import webstore_extension_util
19 import generate_manifest
25 from zipfile
import ZipFile
27 _CHROMEVOX_ID
= 'kgejglhpjiefppelpmljglcjbhoiplfn'
28 _SCRIPT_DIR
= os
.path
.dirname(os
.path
.abspath(__file__
))
29 _CHROME_SOURCE_DIR
= os
.path
.normpath(
31 _SCRIPT_DIR
, *[os
.path
.pardir
] * 6))
34 0, os
.path
.join(_CHROME_SOURCE_DIR
, 'build', 'util'))
37 # A list of files (or directories) to exclude from the webstore build.
40 'manifest_guest.json',
44 def CreateOptionParser():
45 parser
= optparse
.OptionParser(description
=__doc__
)
47 '%prog --client_secret <client_secret> extension_id:extension_path ...')
48 parser
.add_option('-c', '--client_secret', dest
='client_secret',
49 action
='store', metavar
='CLIENT_SECRET')
50 parser
.add_option('-p', '--publish', action
='store_true',
51 help='publish the extension(s)')
56 '''Returns the chrome version string.'''
57 filename
= os
.path
.join(_CHROME_SOURCE_DIR
, 'chrome', 'VERSION')
58 values
= version
.fetch_values([filename
])
59 return version
.subst_template('@MAJOR@.@MINOR@.@BUILD@.@PATCH@', values
)
62 def MakeChromeVoxManifest():
63 '''Create a manifest for the webstore.
66 Temporary file with generated manifest.
68 new_file
= tempfile
.NamedTemporaryFile(mode
='w+a', bufsize
=0)
69 in_file_name
= os
.path
.join(_SCRIPT_DIR
, os
.path
.pardir
,
70 'manifest.json.jinja2')
72 'is_chromevox_classic': '1',
73 'is_guest_manifest': '0',
74 'is_js_compressed': '1',
75 'set_version': GetVersion()
77 generate_manifest
.processJinjaTemplate(in_file_name
, new_file
.name
, context
)
81 def RunInteractivePrompt(client_secret
, output_path
):
85 print 'g get upload status'
86 print 't publish trusted tester'
87 print 'p publish public'
89 input = raw_input('Please select an option: ')
92 print ('Upload status: %s' %
93 webstore_extension_util
.GetUploadStatus(client_secret
).read())
95 print ('Uploaded with status: %s' %
96 webstore_extension_util
.PostUpload(output_path
.name
, client_secret
))
98 print ('Published to trusted testers with status: %s' %
99 webstore_extension_util
.PostPublishTrustedTesters(
100 client_secret
).read())
102 print ('Published to public with status: %s' %
103 webstore_extension_util
.PostPublish(client_secret
).read())
107 print 'Unrecognized option: %s' % input
110 options
, args
= CreateOptionParser().parse_args()
111 if len(args
) < 1 or not options
.client_secret
:
112 print 'Expected at least one argument and --client_secret flag'
116 client_secret
= options
.client_secret
118 for extension
in args
:
119 webstore_extension_util
.g_app_id
, extension_path
= extension
.split(':')
120 output_path
= tempfile
.NamedTemporaryFile()
121 extension_path
= os
.path
.expanduser(extension_path
)
123 is_chromevox
= webstore_extension_util
.g_app_id
== _CHROMEVOX_ID
125 with
ZipFile(output_path
, 'w') as zip:
126 for root
, dirs
, files
in os
.walk(extension_path
):
127 rel_path
= os
.path
.join(os
.path
.relpath(root
, extension_path
), '')
129 if is_chromevox
and rel_path
in EXCLUDE_PATHS
:
132 for extension_file
in files
:
133 if is_chromevox
and extension_file
in EXCLUDE_PATHS
:
136 zip.write(os
.path
.join(root
, extension_file
),
137 os
.path
.join(rel_path
, extension_file
))
140 manifest_file
= MakeChromeVoxManifest()
141 zip.write(manifest_file
.name
, 'manifest.json')
143 print 'Created extension zip file in %s' % output_path
.name
144 print 'Please run manual smoke tests before proceeding.'
146 print('Uploading...%s' %
147 webstore_extension_util
.PostUpload(output_path
.name
, client_secret
))
148 print('publishing...%s' %
149 webstore_extension_util
.PostPublish(client_secret
).read())
151 RunInteractivePrompt(client_secret
, output_path
)
154 if __name__
== '__main__':