def freeze(debug=False): """ Compile your application to a standalone executable """ # Import respective functions late to avoid circular import # fbs <-> fbs.freeze.X. app_name = SETTINGS['app_name'] if is_mac(): from fbs.freeze.mac import freeze_mac freeze_mac(debug=debug) executable = 'target/%s.app/Contents/MacOS/%s' % (app_name, app_name) else: executable = join('target', app_name, app_name) if is_windows(): from fbs.freeze.windows import freeze_windows freeze_windows(debug=debug) executable += '.exe' elif is_linux(): if is_ubuntu(): from fbs.freeze.ubuntu import freeze_ubuntu freeze_ubuntu(debug=debug) elif is_arch_linux(): from fbs.freeze.arch import freeze_arch freeze_arch(debug=debug) elif is_fedora(): from fbs.freeze.fedora import freeze_fedora freeze_fedora(debug=debug) else: from fbs.freeze.linux import freeze_linux freeze_linux(debug=debug) else: raise RuntimeError('Unsupported OS') _LOG.info( "Done. You can now run `%s`. If that doesn't work, see " "https://build-system.fman.io/troubleshooting.", executable)
def freeze(debug=False): """ Compile your application to a standalone executable """ # Import respective functions late to avoid circular import # fbs <-> fbs.freeze.X: if is_windows(): from fbs.freeze.windows import freeze_windows freeze_windows(debug=debug) elif is_mac(): from fbs.freeze.mac import freeze_mac freeze_mac(debug=debug) elif is_linux(): if is_ubuntu(): from fbs.freeze.ubuntu import freeze_ubuntu freeze_ubuntu(debug=debug) elif is_arch_linux(): from fbs.freeze.arch import freeze_arch freeze_arch(debug=debug) elif is_fedora(): from fbs.freeze.fedora import freeze_fedora freeze_fedora(debug=debug) else: from fbs.freeze.linux import freeze_linux freeze_linux(debug=debug) else: raise RuntimeError('Unsupported OS')
def release(): """ Bump version and run clean,freeze,...,upload """ require_existing_project() version = SETTINGS['version'] next_version = _get_next_version(version) release_version = prompt_for_value('Release version', default=next_version) activate_profile('release') SETTINGS['version'] = release_version log_level = _LOG.level if log_level == logging.NOTSET: _LOG.setLevel(logging.WARNING) try: clean() freeze() if is_windows() and _has_windows_codesigning_certificate(): sign() installer() if (is_windows() and _has_windows_codesigning_certificate()) or \ is_arch_linux() or is_fedora(): sign_installer() repo() finally: _LOG.setLevel(log_level) upload() base_json = 'src/build/settings/base.json' update_json(path(base_json), {'version': release_version}) _LOG.info('Also, %s was updated with the new version.', base_json)
def installer(): """ Create an installer for your app """ require_existing_project() if not exists(path('${freeze_dir}')): raise FbsError( 'It seems your app has not yet been frozen. Please run:\n' ' fbs freeze') linux_distribution_not_supported_msg = \ "Your Linux distribution is not supported, sorry. " \ "You can run `fbs buildvm` followed by `fbs runvm` to start a Docker " \ "VM of a supported distribution." try: installer_fname = SETTINGS['installer'] except KeyError: if is_linux(): raise FbsError(linux_distribution_not_supported_msg) raise out_file = join('target', installer_fname) msg_parts = ['Created %s.' % out_file] if is_windows(): from fbs.installer.windows import create_installer_windows create_installer_windows() elif is_mac(): from fbs.installer.mac import create_installer_mac create_installer_mac() elif is_linux(): app_name = SETTINGS['app_name'] if is_ubuntu(): from fbs.installer.ubuntu import create_installer_ubuntu create_installer_ubuntu() install_cmd = 'sudo dpkg -i ' + out_file remove_cmd = 'sudo dpkg --purge ' + app_name elif is_arch_linux(): from fbs.installer.arch import create_installer_arch create_installer_arch() install_cmd = 'sudo pacman -U ' + out_file remove_cmd = 'sudo pacman -R ' + app_name elif is_fedora(): from fbs.installer.fedora import create_installer_fedora create_installer_fedora() install_cmd = 'sudo dnf install ' + out_file remove_cmd = 'sudo dnf remove ' + app_name else: raise FbsError(linux_distribution_not_supported_msg) msg_parts.append( 'You can for instance install it via the following command:\n' ' %s\n' 'This places it in /opt/%s. To uninstall it again, you can use:\n' ' %s' % (install_cmd, app_name, remove_cmd)) else: raise FbsError('Unsupported OS') _LOG.info(' '.join(msg_parts))
def sign_installer(): """ Sign installer, so the user's OS trusts it """ require_existing_project() if is_arch_linux(): from fbs.sign_installer.arch import sign_installer_arch sign_installer_arch() elif is_fedora(): from fbs.sign_installer.fedora import sign_installer_fedora sign_installer_fedora() else: _LOG.info('This command is not (yet) supported on this platform.')
def init(project_dir): """ Call this if you are not invoking `python -m fbs` or fbs.cmdline.main(). """ SETTINGS['project_dir'] = abspath(project_dir) activate_profile('base') activate_profile(platform.name().lower()) if is_linux(): if is_ubuntu(): activate_profile('ubuntu') elif is_arch_linux(): activate_profile('arch') elif is_fedora(): activate_profile('fedora')
def get_default_profiles(): result = ['base'] # The "secret" profile lets the user store sensitive settings such as # passwords in src/build/settings/secret.json. When using Git, the user can # exploit this by adding secret.json to .gitignore, thus preventing it from # being uploaded to services such as GitHub. result.append('secret') result.append(platform.name().lower()) if is_linux(): if is_ubuntu(): result.append('ubuntu') elif is_arch_linux(): result.append('arch') elif is_fedora(): result.append('fedora') return result
def freeze(debug=False): """ Compile your code to a standalone executable """ require_existing_project() if not _has_module('PyInstaller'): raise FbsError("Could not find PyInstaller. Maybe you need to:\n" " pip install PyInstaller==3.4") version = SETTINGS['version'] if not is_valid_version(version): raise FbsError( 'Invalid version detected in settings. It should be three\n' 'numbers separated by dots, such as "1.2.3". You have:\n\t"%s".\n' 'Usually, this can be fixed in src/build/settings/base.json.' % version) # Import respective functions late to avoid circular import # fbs <-> fbs.freeze.X. app_name = SETTINGS['app_name'] if is_mac(): from fbs.freeze.mac import freeze_mac freeze_mac(debug=debug) executable = 'target/%s.app/Contents/MacOS/%s' % (app_name, app_name) else: executable = join('target', app_name, app_name) if is_windows(): from fbs.freeze.windows import freeze_windows freeze_windows(debug=debug) executable += '.exe' elif is_linux(): if is_ubuntu(): from fbs.freeze.ubuntu import freeze_ubuntu freeze_ubuntu(debug=debug) elif is_arch_linux(): from fbs.freeze.arch import freeze_arch freeze_arch(debug=debug) elif is_fedora(): from fbs.freeze.fedora import freeze_fedora freeze_fedora(debug=debug) else: from fbs.freeze.linux import freeze_linux freeze_linux(debug=debug) else: raise FbsError('Unsupported OS') _LOG.info( "Done. You can now run `%s`. If that doesn't work, see " "https://build-system.fman.io/troubleshooting.", executable)
def freeze(debug=False): """ Compile your code to a standalone executable """ require_existing_project() if not _has_module('PyInstaller'): raise FbsError( "Could not find PyInstaller. Maybe you need to:\n" " pip install PyInstaller==3.4" ) # Import respective functions late to avoid circular import # fbs <-> fbs.freeze.X. app_name = SETTINGS['app_name'] if is_mac(): from fbs.freeze.mac import freeze_mac freeze_mac(debug=debug) executable = 'target/%s.app/Contents/MacOS/%s' % (app_name, app_name) else: executable = join('target', app_name, app_name) if is_windows(): from fbs.freeze.windows import freeze_windows freeze_windows(debug=debug) executable += '.exe' elif is_linux(): if is_ubuntu(): from fbs.freeze.ubuntu import freeze_ubuntu freeze_ubuntu(debug=debug) elif is_arch_linux(): from fbs.freeze.arch import freeze_arch freeze_arch(debug=debug) elif is_fedora(): from fbs.freeze.fedora import freeze_fedora freeze_fedora(debug=debug) else: from fbs.freeze.linux import freeze_linux freeze_linux(debug=debug) else: raise FbsError('Unsupported OS') _LOG.info( "Done. You can now run `%s`. If that doesn't work, see " "https://build-system.fman.io/troubleshooting.", executable )
def release(version=None): """ Bump version and run clean,freeze,...,upload """ require_existing_project() if version is None: curr_version = SETTINGS['version'] next_version = _get_next_version(curr_version) release_version = prompt_for_value('Release version', default=next_version) elif version == 'current': release_version = SETTINGS['version'] else: release_version = version if not is_valid_version(release_version): if not is_valid_version(version): raise FbsError( 'The release version of your app is invalid. It should be ' 'three\nnumbers separated by dots, such as "1.2.3". ' 'You have: "%s".' % release_version) activate_profile('release') SETTINGS['version'] = release_version log_level = _LOG.level if log_level == logging.NOTSET: _LOG.setLevel(logging.WARNING) try: clean() freeze() if is_windows() and _has_windows_codesigning_certificate(): sign() installer() if (is_windows() and _has_windows_codesigning_certificate()) or \ is_arch_linux() or is_fedora(): sign_installer() if _repo_is_supported(): repo() finally: _LOG.setLevel(log_level) upload() base_json = 'src/build/settings/base.json' update_json(path(base_json), {'version': release_version}) _LOG.info('Also, %s was updated with the new version.', base_json)
def sign_installer(): """ Sign installer, so the user's OS trusts it """ if is_mac(): _LOG.info('fbs does not yet implement `sign_installer` on macOS.') return if is_ubuntu(): _LOG.info('Ubuntu does not support signing installers.') return require_installer() if is_windows(): from fbs.sign_installer.windows import sign_installer_windows sign_installer_windows() elif is_arch_linux(): from fbs.sign_installer.arch import sign_installer_arch sign_installer_arch() elif is_fedora(): from fbs.sign_installer.fedora import sign_installer_fedora sign_installer_fedora() _LOG.info('Signed %s.', join('target', SETTINGS['installer']))
def installer(): """ Create an installer for your app """ require_existing_project() out_file = join('target', SETTINGS['installer']) msg_parts = ['Created %s.' % out_file] if is_windows(): from fbs.installer.windows import create_installer_windows create_installer_windows() elif is_mac(): from fbs.installer.mac import create_installer_mac create_installer_mac() elif is_linux(): app_name = SETTINGS['app_name'] if is_ubuntu(): from fbs.installer.ubuntu import create_installer_ubuntu create_installer_ubuntu() install_cmd = 'sudo dpkg -i ' + out_file remove_cmd = 'sudo dpkg --purge ' + app_name elif is_arch_linux(): from fbs.installer.arch import create_installer_arch create_installer_arch() install_cmd = 'sudo pacman -U ' + out_file remove_cmd = 'sudo pacman -R ' + app_name elif is_fedora(): from fbs.installer.fedora import create_installer_fedora create_installer_fedora() install_cmd = 'sudo dnf install ' + out_file remove_cmd = 'sudo dnf remove ' + app_name else: raise FbsError('Unsupported Linux distribution') msg_parts.append( 'You can for instance install it via the following command:\n' ' %s\n' 'This places it in /opt/%s. To uninstall it again, you can use:\n' ' %s' % (install_cmd, app_name, remove_cmd)) else: raise FbsError('Unsupported OS') _LOG.info(' '.join(msg_parts))
def installer(): """ Create an installer for your app """ if is_windows(): from fbs.installer.windows import create_installer_windows create_installer_windows() elif is_mac(): from fbs.installer.mac import create_installer_mac create_installer_mac() elif is_linux(): if is_ubuntu(): from fbs.installer.ubuntu import create_installer_ubuntu create_installer_ubuntu() elif is_arch_linux(): from fbs.installer.arch import create_installer_arch create_installer_arch() elif is_fedora(): from fbs.installer.fedora import create_installer_fedora create_installer_fedora() else: raise RuntimeError('Unsupported Linux distribution') else: raise RuntimeError('Unsupported OS')
def upload(): """ Upload installer and repository to fbs.sh """ require_existing_project() try: username = SETTINGS['fbs_user'] password = SETTINGS['fbs_pass'] except KeyError as e: raise FbsError( 'Could not find setting "%s". You may want to invoke one of the ' 'following:\n' ' * fbs register\n' ' * fbs login' % (e.args[0],) ) from None _upload_repo(username, password) app_name = SETTINGS['app_name'] url = lambda p: 'https://fbs.sh/%s/%s/%s' % (username, app_name, p) message = 'Done! ' pkg_name = app_name.lower() installer_url = url(SETTINGS['installer']) if is_linux(): message += 'Your users can now install your app via the following ' \ 'commands:\n' format_commands = lambda *cmds: '\n'.join(' ' + c for c in cmds) repo_url = url(SETTINGS['repo_subdir']) if is_ubuntu(): message += format_commands( "sudo apt-get install apt-transport-https", "wget -qO - %s | sudo apt-key add -" % url('public-key.gpg'), "echo 'deb [arch=amd64] %s stable main' | " % repo_url + "sudo tee /etc/apt/sources.list.d/%s.list" % pkg_name, "sudo apt-get update", "sudo apt-get install " + pkg_name ) message += '\nIf they already have your app installed, they can ' \ 'force an immediate update via:\n' message += format_commands( 'sudo apt-get update ' '-o Dir::Etc::sourcelist="/etc/apt/sources.list.d/%s.list" ' '-o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0"' % pkg_name, 'sudo apt-get install --only-upgrade ' + pkg_name ) elif is_arch_linux(): message += format_commands( "curl -O %s && " % url('public-key.gpg') + "sudo pacman-key --add public-key.gpg && " + "sudo pacman-key --lsign-key %s && " % SETTINGS['gpg_key'] + "rm public-key.gpg", "echo -e '\\n[%s]\\nServer = %s' | sudo tee -a /etc/pacman.conf" % (app_name, repo_url), "sudo pacman -Syu " + pkg_name ) message += '\nIf they already have your app installed, they can ' \ 'force an immediate update via:\n' message += format_commands('sudo pacman -Syu --needed ' + pkg_name) elif is_fedora(): message += format_commands( "sudo rpm -v --import " + url('public-key.gpg'), "sudo dnf config-manager --add-repo %s/%s.repo" % (repo_url, app_name), "sudo dnf install " + pkg_name ) message += "\n(On CentOS, replace 'dnf' by 'yum' and " \ "'dnf config-manager' by 'yum-config-manager'.)" message += '\nIf they already have your app installed, they can ' \ 'force an immediate update via:\n' message += \ format_commands('sudo dnf upgrade %s --refresh' % pkg_name) message += '\nThis is for Fedora. For CentOS, use:\n' message += format_commands( 'sudo yum clean all && sudo yum upgrade ' + pkg_name ) else: raise FbsError('This Linux distribution is not supported.') message += '\nFinally, your users can also install without automatic ' \ 'updates by downloading:\n ' + installer_url extra = {'wrap': False} else: message += 'Your users can now download and install %s.' % installer_url extra = None _LOG.info(message, extra=extra)
def _repo_is_supported(): return is_ubuntu() or is_arch_linux() or is_fedora()
def repo(): """ Generate files for automatic updates """ require_existing_project() if not _repo_is_supported(): raise FbsError('This command is not supported on this platform.') app_name = SETTINGS['app_name'] pkg_name = app_name.lower() try: gpg_key = SETTINGS['gpg_key'] except KeyError: raise FbsError( 'GPG key for code signing is not configured. You might want to ' 'either\n' ' 1) run `fbs gengpgkey` or\n' ' 2) set "gpg_key" and "gpg_pass" in src/build/settings/.' ) if is_ubuntu(): from fbs.repo.ubuntu import create_repo_ubuntu if not SETTINGS['description']: _LOG.info( 'Hint: Your app\'s "description" is empty. Consider setting it ' 'in src/build/settings/linux.json.' ) create_repo_ubuntu() _LOG.info( 'Done. You can test the repository with the following commands:\n' ' echo "deb [arch=amd64] file://%s stable main" ' '| sudo tee /etc/apt/sources.list.d/%s.list\n' ' sudo apt-key add %s\n' ' sudo apt-get update\n' ' sudo apt-get install %s\n' 'To revert these changes:\n' ' sudo dpkg --purge %s\n' ' sudo apt-key del %s\n' ' sudo rm /etc/apt/sources.list.d/%s.list\n' ' sudo apt-get update', path('target/repo'), pkg_name, path('src/sign/linux/public-key.gpg'), pkg_name, pkg_name, gpg_key, pkg_name, extra={'wrap': False} ) elif is_arch_linux(): from fbs.repo.arch import create_repo_arch create_repo_arch() _LOG.info( "Done. You can test the repository with the following commands:\n" " sudo cp /etc/pacman.conf /etc/pacman.conf.bu\n" " echo -e '\\n[%s]\\nServer = file://%s' " "| sudo tee -a /etc/pacman.conf\n" " sudo pacman-key --add %s\n" " sudo pacman-key --lsign-key %s\n" " sudo pacman -Syu %s\n" "To revert these changes:\n" " sudo pacman -R %s\n" " sudo pacman-key --delete %s\n" " sudo mv /etc/pacman.conf.bu /etc/pacman.conf", app_name, path('target/repo'), path('src/sign/linux/public-key.gpg'), gpg_key, pkg_name, pkg_name, gpg_key, extra={'wrap': False} ) else: assert is_fedora() from fbs.repo.fedora import create_repo_fedora create_repo_fedora() _LOG.info( "Done. You can test the repository with the following commands:\n" " sudo rpm -v --import %s\n" " sudo dnf config-manager --add-repo file://%s/target/repo\n" " sudo dnf install %s\n" "To revert these changes:\n" " sudo dnf remove %s\n" " sudo rm /etc/yum.repos.d/*%s*.repo\n" " sudo rpm --erase gpg-pubkey-%s", path('src/sign/linux/public-key.gpg'), SETTINGS['project_dir'], pkg_name, pkg_name, app_name, gpg_key[-8:].lower(), extra={'wrap': False} )