blob: ccb524474fe0a43f2dec34ba0fb016559288df4a [file] [log] [blame]
#!/usr/bin/env python3.8
# Copyright 2023 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import json
import subprocess
import shlex
import sys
from pathlib import Path
from typing import List
from terminal import Terminal
DESCRIPTION = '''
Publishes a given set of packages.
TODO(fxbug.dev/127875): Currently only cache packages are supported by this
tool.
'''
def run(*command: str, failure_message: str, **kwargs) -> None:
command = shlex.join([str(part) for part in command])
try:
subprocess.check_call(command, shell=True, **kwargs)
except subprocess.SubprocessError as e:
Terminal.error(f'Command failed: {command}')
Terminal.fatal(failure_message)
def fx_command(*command: str) -> List[str]:
return [
'bash',
'-c',
' '.join(
[
'.',
str(
(Path(__file__).parent.parent / 'lib' /
'vars.sh').resolve()), '&&', 'fx-config-read', '&&',
'fx-command-run',
shlex.join([str(part) for part in command])
]),
]
def main() -> int:
parser = argparse.ArgumentParser(
prog='fx publish',
formatter_class=argparse.RawTextHelpFormatter,
description=DESCRIPTION,
)
parser.add_argument(
'packages',
help=
'Specify packages to publish. Currently, only cache packages are supported.',
action='store',
nargs='+',
)
parser.add_argument(
'--repo',
help=
'Publish to this repo directory (relative to the build directory); defaults to `amber-files`.',
default='amber-files',
)
parser.add_argument(
'--no-build',
dest='build',
default=True,
help='Publish only, skipping `fx build`.',
action='store_false',
)
parser.add_argument(
'--quiet',
help='Suppress messages.',
action='store_true',
)
parser.add_argument(
'--stamp',
help='Specify a stamp file to write to after publishing.',
)
args = parser.parse_args()
Terminal.suppress = args.quiet
build_dir = Path('.').resolve()
package_tool = build_dir / 'host-tools' / 'package-tool'
repo = build_dir / args.repo
publish_tool_opts = (repo /
'publish_tool_opts').read_text().strip().split('\n')
# Collect ninja targets.
ninja_targets = ['build/images/updates:prepare_publish']
packages_to_publish = []
for packages in set(args.packages):
if packages == 'cache':
ninja_targets.append('assembly_cache_packages.list')
packages_to_publish.append(
build_dir / 'assembly_cache_packages.list')
else:
Terminal.fatal(f'Unrecognized packages "{packages}".')
# Build step.
if args.build:
run(
*fx_command('build', *ninja_targets),
failure_message='Build failures!',
)
# Publish the packages.
run(
package_tool,
'repository',
'publish',
repo,
*publish_tool_opts,
'--package-list',
*packages_to_publish,
failure_message='An internal error occured while publishing.',
)
# Report package publishing.
publish_count = sum(
[
len(json.loads(file.read_text())['content']['manifests'])
for file in packages_to_publish
])
publish_count_msg = f'Published {publish_count} packages'
if not Terminal.suppress:
if subprocess.run(shlex.join(fx_command('is-package-server-running')),
shell=True, capture_output=True).returncode:
Terminal.warn(
f'{publish_count_msg}, but it looks like the package server is not running.'
)
Terminal.warn('You probably need to run "fx serve".')
else:
Terminal.info(f'{publish_count_msg}!')
# Write stamp file.
if args.stamp:
Path(args.stamp).write_text(str(publish_count))
if __name__ == '__main__':
sys.exit(main())