File: upload_html_viewer.py

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (168 lines) | stat: -rwxr-xr-x 5,632 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#!/usr/bin/env python3
# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Update the firebase project hosting the Super Size UI."""

import argparse
import os
import pathlib
import shutil
import subprocess
import sys
import tempfile
import urllib.request
import uuid

_VIEWER_DIR = pathlib.Path(__file__).parent.resolve()
_STATIC_FILES_DIR = _VIEWER_DIR / 'static'

_FIREBASE_PROJECT = 'chrome-supersize'
_PROD_URL = 'https://chrome-supersize.firebaseapp.com/'
_WASM_FILES = [
    'caspian_web.js',
    'caspian_web.wasm',
]
_DEBUG_WASM_FILES = [
    'caspian_web.wasm.debug.wasm',
]

_PROD = 'prod'
_STAGING = 'staging'
_DEV = 'dev'


def _FirebaseLogin():
  """Login into the Firebase CLI"""
  subprocess.check_call(['firebase', 'login', '--no-localhost'])


def _CheckFirebaseCLI():
  """Fail with a proper error message, if Firebase CLI is not installed."""
  if subprocess.call(['firebase', '--version'], stdout=subprocess.DEVNULL) != 0:
    link = 'https://firebase.google.com/docs/cli#install_the_firebase_cli'
    raise Exception('Firebase CLI not installed or not on your PATH. Follow '
                    'the instructions at ' + link + ' to install')


def _FirebaseInitProjectDir(project_dir):
  """Create a firebase.json file that is needed for deployment."""
  static_dir = project_dir / 'public'
  project_dir.joinpath('firebase.json').write_text("""\
{
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/README*",
      "**/.*"
    ]
  }
}
""")
  return static_dir


def _FirebaseDeploy(project_dir, deploy_mode=_PROD):
  """Deploy the project to firebase hosting."""
  if deploy_mode == _DEV:
    subprocess.check_call([
        'firebase', '-P', _FIREBASE_PROJECT, 'emulators:start', '--only',
        'hosting'
    ],
                          cwd=project_dir)
  elif deploy_mode == _STAGING:
    print('Note: deploying to staging requires firebase cli >= 8.12.0')
    subprocess.check_call([
        'firebase', '-P', _FIREBASE_PROJECT, 'hosting:channel:deploy', 'staging'
    ],
                          cwd=project_dir)
  else:
    subprocess.check_call(['firebase', 'deploy', '-P', _FIREBASE_PROJECT],
                          cwd=project_dir)


def _MaybeDownloadWasmFiles(force_download):
  """Download WASM files if they are missing or stale."""
  if not force_download:
    if not all(_STATIC_FILES_DIR.joinpath(f).exists() for f in _WASM_FILES):
      print(f'Some WASM files do not exist in: {_STATIC_FILES_DIR}')
      force_download = True

  if force_download:
    for f in _WASM_FILES:
      print(f'Downloading: {_PROD_URL + f}')
      with urllib.request.urlopen(_PROD_URL + f) as response:
        with _STATIC_FILES_DIR.joinpath(f).open('wb') as output:
          shutil.copyfileobj(response, output)


def _FillInAndCopyTemplates(project_static_dir):
  """Generate and copy over the templates/sw.js file."""
  src_path = _VIEWER_DIR / 'templates' / 'sw.js'
  dst_path = project_static_dir / 'sw.js'
  cache_hash = uuid.uuid4().hex
  dst_path.write_text(src_path.read_text().replace('{{cache_hash}}',
                                                   cache_hash))


def _CopyStaticFiles(project_static_dir, *, include_debug_wasm):
  shutil.copytree(_STATIC_FILES_DIR, project_static_dir)
  # Don't upload the debug info since it's machine-dependent and large.
  if not include_debug_wasm:
    for f in _DEBUG_WASM_FILES:
      project_static_dir.joinpath(f).unlink(missing_ok=True)


def _Prompt(message):
  """Prompt the user with a message and request affirmative outcome."""
  choice = input(message + ' [y/N] ').lower()
  return choice and choice[0] == 'y'


def main():
  parser = argparse.ArgumentParser()
  deployment_mode_group = parser.add_mutually_exclusive_group(required=True)
  deployment_mode_group.add_argument('--local',
                                     action='store_const',
                                     dest='deploy_mode',
                                     const=_DEV,
                                     help='Deploy a locally hosted server.')
  deployment_mode_group.add_argument(
      '--staging',
      action='store_const',
      dest='deploy_mode',
      const=_STAGING,
      help='Deploy to staging channel (does not support authenticated '
      'requests).')
  deployment_mode_group.add_argument('--prod',
                                     action='store_const',
                                     dest='deploy_mode',
                                     const=_PROD,
                                     help='Deploy to prod.')
  parser.add_argument('--download-wasm',
                      action='store_true',
                      help='Update local copy of WASM files.')
  options = parser.parse_args()

  message = (f'This script deploys the viewer to {_PROD_URL}.\n'
             'Are you sure you want to continue?')

  if options.deploy_mode != _PROD or _Prompt(message):
    _CheckFirebaseCLI()
    if options.deploy_mode != _DEV:
      _FirebaseLogin()
    with tempfile.TemporaryDirectory(prefix='firebase-') as project_dir:
      project_dir = pathlib.Path(project_dir)
      _MaybeDownloadWasmFiles(options.download_wasm)
      project_static_dir = _FirebaseInitProjectDir(project_dir)
      _CopyStaticFiles(project_static_dir,
                       include_debug_wasm=options.deploy_mode == _DEV)
      _FillInAndCopyTemplates(project_static_dir)
      _FirebaseDeploy(project_dir, deploy_mode=options.deploy_mode)
  else:
    print('Nothing was deployed.')


if __name__ == '__main__':
  main()