Exemplo n.º 1
0
def install_remote_dependencies():
    ''' Install dependencies on the remote host. '''
    remote_info('Installing dependencies on the remote')
    if runner.is_script_defined(known_scripts.INSTALL_REMOTE):
        runner.run_script(known_scripts.INSTALL_REMOTE)
    else:
        runner.run_script(known_scripts.INSTALL)
Exemplo n.º 2
0
def test_run_script_send_script_running_notifications(gs_m, gu_m, send_m, gc_m, hi_m, h_m, r_m):
    gs_m.return_value = 'prod'
    gu_m.return_value = 'kabir'
    gc_m.return_value = {
        'scripts': {
            'foo': 'just foo'
        },
        'notified_hooks': {
            'scripts': ['foo']
        }
    }

    run_script('foo')

    send_m.assert_called()
    (call1, call2) = send_m.call_args_list

    assert call1[0][0] == RUNNING_SCRIPT_STARTED
    assert call1[0][1]['script'] == 'foo'
    assert call1[0][1]['user'] == 'kabir'
    assert call1[0][1]['stage'] == 'prod'

    assert call2[0][0] == RUNNING_SCRIPT_FINISHED
    assert call2[0][1]['script'] == 'foo'
    assert call2[0][1]['user'] == 'kabir'
    assert call2[0][1]['stage'] == 'prod'
Exemplo n.º 3
0
def run(script):
    ''' Run a custom script. '''
    # Run a custom script defined in the config.
    # Change the current working directory to the node application
    # before running the script.

    with cd(buildman.get_current_path()):
        try:
            runner.run_script(script)
        except RuntimeError as e:
            halt(str(e))
Exemplo n.º 4
0
def build(stage, config):
    '''
    Trigger build script to prepare a build for the given stage.
    '''
    info('Getting the build ready for deployment')

    # Trigger the install script
    runner.run_script(known_scripts.INSTALL, remote=False)

    env_vars = get_build_env_vars(stage, config)

    with shell_env(**env_vars):
        runner.run_script(known_scripts.BUILD, remote=False)
Exemplo n.º 5
0
def start_or_reload_service(has_started=False):
    ''' Start or reload the application service. '''
    with cd(buildman.get_deploy_dir()):
        if runner.is_script_defined(known_scripts.START_OR_RELOAD):
            remote_info('Starting/Reloading the service.')
            runner.run_script(known_scripts.START_OR_RELOAD)

        elif has_started and runner.is_script_defined(known_scripts.RELOAD):
            remote_info('Reloading the service.')
            runner.run_script_safely(known_scripts.RELOAD)

        elif runner.is_script_defined(known_scripts.START):
            remote_info('Starting the service.')
            runner.run_script(known_scripts.START)
Exemplo n.º 6
0
def install_remote_dependencies(commit, current_path, smart_install):
    ''' Install dependencies on the remote host. '''
    history = buildman.load_history()
    prev_build = buildman.get_prev_build_info(history)

    # Check if the installation could be skipped (smart_install).
    can_skip_installation = (
        smart_install and
        prev_build and
        not has_updated_dependencies(prev_build['commit'], commit)
    )

    # Smart install - copy the node_modules directory from the previous deployment
    # if it's usable (no dependencies or package manager files have changed).
    if can_skip_installation:
        runner.run(
            'cp -R {src} {dest}'.format(
                src=os.path.join(prev_build['path'], 'node_modules'),
                dest=os.path.join(current_path, 'node_modules')
            )
        )
        remote_info('Skipping installation - No change in dependencies.')
        return

    # Install dependencies on the remote.
    with cd(current_path):
        remote_info('Installing dependencies on the remote')
        runner.run_script_safely(known_scripts.PRE_INSTALL)

        if runner.is_script_defined(known_scripts.INSTALL_REMOTE):
            runner.run_script_safely(known_scripts.PRE_INSTALL_REMOTE)
            runner.run_script(known_scripts.INSTALL_REMOTE)
            runner.run_script_safely(known_scripts.POST_INSTALL_REMOTE)
        else:
            runner.run_script_safely(known_scripts.INSTALL)

        runner.run_script_safely(known_scripts.POST_INSTALL)
Exemplo n.º 7
0
def services():
    ''' List the services running for the application. '''
    with cd(buildman.get_current_path()):
        runner.run_script(known_scripts.LIST_SERVICES)
Exemplo n.º 8
0
def status():
    ''' Get the status of the service. '''
    with cd(buildman.get_current_path()):
        runner.run_script(known_scripts.STATUS_CHECK)
Exemplo n.º 9
0
def deploy():
    ''' Zero-Downtime deployment for the backend. '''
    config = get_config()
    stage = shell.get_stage()
    is_first_deployment = not buildman.is_remote_setup()

    branch = git.current_branch(remote=False)
    commit = git.last_commit(remote=False, short=True)
    info('Deploying <{branch}:{commit}> to the {stage} server'.format(
        branch=branch, commit=commit, stage=stage))

    tmp_path = fs.get_temp_filename()
    build_dir = buildman.resolve_local_build_dir()
    included_files = config['deployment']['include_files']

    deployer_user = shell.get_user()

    notif.send(notif.DEPLOYMENT_STARTED, {
        'user': deployer_user,
        'branch': branch,
        'stage': stage
    })

    (release_dir, current_path) = buildman.setup_remote()

    timestamp = datetime.utcnow()
    build_id = timestamp.strftime('%Y%m%d%H%M%S')
    build_name = buildman.get_build_name(build_id)
    build_compressed = build_name + '.tar.gz'
    release_path = release_dir + '/' + build_name
    dist_path = build_name + '/dist'

    info('Getting the build ready for deployment')

    # Trigger the install script
    runner.run_script(constants.SCRIPT_INSTALL, remote=False)

    # Trigger the build script.
    #
    # The stage for which the build script is being run is passed
    # via an environment variable STAGE.
    # This could be useful for creating specific builds for
    # different environments.
    with shell_env(STAGE=stage):
        runner.run_script(constants.SCRIPT_BUILD, remote=False)

    info('Compressing the build')
    fs.tar_archive(build_compressed, build_dir, remote=False)

    info('Uploading the build {} to {}'.format(build_compressed, tmp_path))
    fs.upload(build_compressed, tmp_path)

    # Remove the compressed build from the local directory.
    fs.rm(build_compressed, remote=False)

    # Once, the build is uploaded to the remote,
    # set things up in the remote server.
    with cd(release_dir):
        remote_info('Extracting the build {}'.format(build_compressed))
        # Create a new directory for the build in the remote.
        fs.mkdir(dist_path, nested=True)

        # Extract the build.
        fs.tar_extract(tmp_path, dist_path)

        # Remove the uploaded archived from the temp path.
        fs.rm_rf(tmp_path)

        # Upload the files to be included eg: package.json file
        # to the remote build location.
        upload_included_files(included_files, release_path)

        remote_info('Pointing the current symlink to the latest build')
        fs.update_symlink(release_path, current_path)

    # Change directory to the release path.
    with cd(current_path):
        install_remote_dependencies()

    # Start or restart the application service.
    start_or_reload_service(is_first_deployment)

    # Save build history
    buildman.record_history({
        'id': build_id,
        'path': release_path,
        'branch': branch,
        'commit': commit,
        'stage': stage,
        'createdBy': deployer_user,
        'timestamp': timestamp.strftime(buildman.TS_FORMAT)
    })

    # Send deployment finished notification.
    notif.send(notif.DEPLOYMENT_FINISHED, {'branch': branch, 'stage': stage})

    remote_info('Deployment Completed')