コード例 #1
0
ファイル: setup.py プロジェクト: karelsmetana/py-mina
def create_entity(entity_path, entity_type='file', protected=False):
    """
    Creates directory/file and sets proper owner/mode.
    """
    def change_owner(owner_triple):
        """
        Changes unix owner/mode
        """

        run('chmod u+rwx,g+rx,o-rwx ' + entity_path)
        run('chown -R %s:%s %s' % owner_triple)

    # 1) Create file/directory

    if entity_type == 'file':
        run('touch %s' % entity_path)
    else:
        run('mkdir -p %s' % entity_path)

    # 2) Change owner/mode

    if protected:
        protected_owner_user = fetch('protected_owner_user')
        protected_owner_group = fetch('protected_owner_group')

        change_owner(
            (protected_owner_user, protected_owner_group, entity_path))
    else:
        owner_user = fetch('owner_user', default_value=False)
        owner_group = fetch('owner_group', default_value=False)

        if owner_user != False and owner_group != False:
            change_owner((owner_user, owner_group, entity_path))
        else:
            run('chmod o-rwx ' + entity_path)
コード例 #2
0
ファイル: deploy.py プロジェクト: py-mina-deploy/py-mina
def rollback_release():
    """
    Rollbacks latest release
    """

    ensure('current_path')

    releases_path = fetch('releases_path')

    with (settings(show('debug'))):
        with cd(releases_path):
            echo_subtask('Finding previous release for rollback')
            rollback_release_number = run(
                'ls -1A | sort -n | tail -n 2 | head -n 1')

            if int(rollback_release_number) > 0:
                echo_subtask('Linking previous release to current')
                run('ln -nfs %s/%s %s' %
                    (releases_path, rollback_release_number,
                     fetch('current_path')))

                echo_subtask('Finding latest release')
                current_release = run('ls -1A | sort -n | tail -n 1')

                if int(current_release) > 0:
                    echo_subtask('Removing latest release')
                    run('rm -rf %s/%s' % (releases_path, current_release))
                else:
                    abort('Can\'t find latest release for remove.')
            else:
                abort('Can\'t find previous release for rollback.')
コード例 #3
0
ファイル: deploy.py プロジェクト: py-mina-deploy/py-mina
def move_build_to_releases():
    """
    Moves current build folder to releases path
    """

    ensure('build_to')
    ensure('release_to')

    echo_subtask('Moving from build path to release path')

    run('mv %s %s' % (fetch('build_to'), fetch('release_to')))
コード例 #4
0
ファイル: deploy.py プロジェクト: py-mina-deploy/py-mina
def link_release_to_current():
    """
    Creates current release symlink in `deploy_to` path
    """

    ensure('current_path')

    release_to = fetch('release_to')

    echo_subtask("Linking release to current")

    with cd(release_to):
        run('ln -nfs %s %s' % (release_to, fetch('current_path')))
コード例 #5
0
def fetch_new_commits():
    """
    Fetches new git commits
    """

    ensure('scm')
    ensure('repository')
    ensure('branch')

    echo_subtask("Fetching new commits")

    with cd(fetch('scm')):
        run('git fetch {0} "{1}:{1}" --force'.format(fetch('repository'),
                                                     fetch('branch')))
コード例 #6
0
ファイル: git.py プロジェクト: karelsmetana/py-mina
def use_git_branch():
    """
    Clones repository to build dir
    """

    ensure('scm')
    ensure('branch')

    build_to = fetch('build_to')

    echo_subtask("Copying code from repository to build folder")

    run('git clone {0} {1} --recursive --branch {2}'.format(
        fetch('scm'), build_to, fetch('branch')))
    run('rm -rf %s' % os.path.join(build_to, '.git'))
コード例 #7
0
ファイル: setup.py プロジェクト: karelsmetana/py-mina
def add_repo_to_known_hosts():
    """
    Adds repository host to known hosts if possible
    """

    maybe_repository = fetch('repository', default_value='')

    if maybe_repository:
        # Parse repo host
        repo_host_array = re.compile('(@|://)').split(maybe_repository)
        repo_host_part = repo_host_array[-1] if repo_host_array else ''
        repo_host_match = re.compile(':|\/').split(repo_host_part)
        repo_host = repo_host_match[0] if repo_host_match else ''

        # Exit if no host
        if repo_host == '':
            return

        # Parse port
        repo_port_match = re.search(r':([0-9]+)', maybe_repository)
        repo_port = repo_port_match.group(1) if bool(repo_port_match) else 22

        echo_subtask('Adding repository to known hosts')

        add_to_known_hosts(repo_host, repo_port)
コード例 #8
0
ファイル: deploy.py プロジェクト: py-mina-deploy/py-mina
def discover_latest_release():
    """
    Connects to remote server and discovers next release number
    """

    releases_path = fetch('releases_path')

    echo_subtask("Discovering latest release number")

    # Get latest release number
    with settings(hide('warnings'), warn_only=True):
        if run('test -d %s' % releases_path).failed:
            last_release_number = 0
            create_entity(releases_path,
                          entity_type='directory',
                          protected=False)
        else:
            releases_respond = run('ls -1p %s | sed "s/\///g"' % releases_path)
            releases_dirs = list(
                filter(lambda x: len(x) != 0, releases_respond.split('\r\n')))

            if len(releases_dirs) > 0:
                last_release_number = max(map(lambda x: int(x),
                                              releases_dirs)) or 0
            else:
                last_release_number = 0

    release_number = last_release_number + 1

    # Set release info to config
    set('release_number', release_number)
    set('release_to', '/'.join([releases_path, str(release_number)]))
コード例 #9
0
ファイル: setup.py プロジェクト: karelsmetana/py-mina
def create_shared_paths():
    """
    Creates shared (+protected) files/dirs and sets unix owner/mode
    """

    global shared_path
    shared_path = fetch('shared_path')

    def create_dirs(directories, protected=False):
        global shared_path

        for sdir in directories:
            create_entity(os.path.join(shared_path, sdir),
                          entity_type='directory',
                          protected=protected)

    def create_files(files, protected=False):
        global shared_path

        for sfile in files:
            directory, filename_ = os.path.split(sfile)

            if directory:
                create_entity(os.path.join(shared_path, directory),
                              entity_type='directory',
                              protected=protected)

            filepath = os.path.join(shared_path, sfile)
            create_entity(filepath, entity_type='file', protected=protected)

            recommendation_tuple = (env.host_string, filepath)
            echo_status(
                '\n=====> Don\'t forget to update shared file:\n[%s] %s\n' %
                recommendation_tuple,
                error=True)

    echo_subtask('Creating shared paths')

    # Shared
    create_dirs(fetch('shared_dirs', default_value=[]), protected=False)
    create_files(fetch('shared_files', default_value=[]), protected=False)

    # Protected
    create_dirs(fetch('protected_shared_dirs', default_value=[]),
                protected=True)
    create_files(fetch('protected_shared_files', default_value=[]),
                 protected=True)
コード例 #10
0
def use_git_branch():
    """
    Clones repository to build dir
    """

    ensure('scm')
    ensure('branch')

    build_to = fetch('build_to')

    echo_subtask("Copying code from repository to build folder")

    run('git clone {0} {1} --recursive --branch {2}'.format(
        fetch('scm'), build_to, fetch('branch')))

    with settings(warn_only=True):
        run('rm -rf %s' % '/'.join([build_to, '.git']))
コード例 #11
0
ファイル: deploy.py プロジェクト: py-mina-deploy/py-mina
def force_unlock():
    """
    Forces a deploy unlock
    """

    echo_subtask("Removing `deploy.lock` file")

    run('rm -f %s' % '/'.join([fetch('deploy_to'), 'deploy.lock']))
コード例 #12
0
ファイル: deploy.py プロジェクト: py-mina-deploy/py-mina
def check_lock():
    """
    Aborts deploy if lock file is found
    """
    def run_abort():
        abort("Another deploy in progress")

    echo_subtask("Checking `deploy.lock` file presence")

    with settings(hide('warnings'), warn_only=True):
        if run('test -f %s' %
               '/'.join([fetch('deploy_to'), 'deploy.lock'])).succeeded:
            if fetch('ask_unlock_if_locked', default_value=False):
                if not confirm('Deploy lockfile exists. Continue?'):
                    run_abort()
            else:
                run_abort()
コード例 #13
0
ファイル: deploy.py プロジェクト: py-mina-deploy/py-mina
def print_deploy_stats(task_name, start_time):
    if fetch('verbose') == True:
        print_verbose()

    error_states = get_error_states()

    if error_states:
        echo_task('Deploy errors', error=True)

        for error_state in error_states:
            echo_comment(('\n[ERROR]\n%s' % state.get(error_state)),
                         error=True)

    if state.get('success'):
        print(yellow('\n-----> Release number: %s' % fetch('release_number')))

    print_stats_args = [task_name, start_time]
    if state.get('success') != True: print_stats_args.append(True)
    print_task_stats(*print_stats_args)
コード例 #14
0
def cleanup_releases():
    """
    Cleans up old releases
    """

    ensure('releases_path')

    releases_count = str(fetch('keep_releases'))

    echo_subtask("Cleaning up old realeses. Keeping latest %s" %
                 releases_count)

    with cd(fetch('releases_path')), show('debug'):
        cmd = '''
count=$(ls -A1 | sort -rn | wc -l)
remove=$((count > %s ? count - %s : 0))
ls -A1 | sort -rn | tail -n $remove | xargs rm -rf {}'''

        run(cmd % (releases_count, releases_count))
コード例 #15
0
ファイル: deploy.py プロジェクト: py-mina-deploy/py-mina
def remove_build_path():
    """
    Removes a temporary build dir
    """

    echo_subtask("Removing build path")

    with settings(hide('stdout', 'warnings'), warn_only=True):
        builds_path = '/'.join([fetch('deploy_to'), 'tmp', 'build-*'])

        run('rm -rf %s' % builds_path)
コード例 #16
0
def lock():
    """
    Locks deploy
    Parallel deploys are not allowed
    """

    ensure('build_to')

    echo_subtask("Creating `deploy.lock` file")

    run('touch %s' % os.path.join(fetch('deploy_to'), 'deploy.lock'))
コード例 #17
0
def maybe_clone_git_repository():
    """
    Clones bare git repository on first deploy
    """

    ensure('repository')

    scm_path = fetch('scm')

    with settings(hide('warnings'), warn_only=True):
        echo_subtask('Ensuring git repository presence')

        if run('test -d %s' % scm_path).failed:
            create_entity(scm_path, entity_type='directory', protected=False)

        if run('test -f %s' % '/'.join([scm_path, 'HEAD'])).failed:
            echo_subtask("Cloning bare git repository")

            with settings(hide('output')):
                run('git clone {0} {1} --bare'.format(fetch('repository'),
                                                      scm_path))
コード例 #18
0
ファイル: deploy.py プロジェクト: py-mina-deploy/py-mina
def lock():
    """
    Locks deploy
    Parallel deploys are not allowed
    """

    ensure('build_to')

    echo_subtask("Creating `deploy.lock` file")

    create_entity('/'.join([fetch('deploy_to'), 'deploy.lock']),
                  entity_type='file',
                  protected=False)
コード例 #19
0
ファイル: deploy.py プロジェクト: py-mina-deploy/py-mina
def cleanup_releases():
    """
    Cleans up old releases
    """

    ensure('releases_path')
    ensure('keep_releases')

    releases_count = str(fetch('keep_releases'))

    if (releases_count == "-1"):
        return

    echo_subtask("Cleaning up old realeses. Keeping latest %s" %
                 releases_count)

    with cd(fetch('releases_path')), show('debug'):
        use_sudo = 'sudo' if fetch('sudo_on_cleanup_releases') else ''
        cmd = '''
count=$(ls -A1 | sort -rn | wc -l)
remove=$((count > %s ? count - %s : 0))
ls -A1 | sort -rn | tail -n $remove | xargs %s rm -rf {}'''
        run(cmd % (releases_count, releases_count, use_sudo))
コード例 #20
0
ファイル: setup.py プロジェクト: karelsmetana/py-mina
def create_required_structure():
    """
    Creates required folders (tmp, releases, shared) in `deploy_to` path
    """

    deploy_to = fetch('deploy_to')

    echo_subtask('Creating required structure')

    create_entity(deploy_to, entity_type='directory', protected=False)

    for required_path in ['shared', 'releases', 'tmp']:
        create_entity(os.path.join(deploy_to, required_path),
                      entity_type='directory',
                      protected=False)
コード例 #21
0
ファイル: deploy.py プロジェクト: py-mina-deploy/py-mina
def create_build_path():
    """
    Creates tmp dir for building app. 

    Folder will be:
        * deleted -> if build fails
        * moved to releases -> if build succeeds
    """

    ensure('build_to')

    echo_subtask("Creating build path")

    with settings(hide('warnings'), warn_only=True):
        build_path = fetch('build_to')

        if run('test -d %s' % build_path).failed:
            create_entity(build_path, entity_type='directory', protected=False)
コード例 #22
0
def create_entity(entity_path, entity_type='file', protected=False):
    """
    Creates directory/file and sets proper owner/mode.
    """

    chmod_sudo = 'sudo ' if fetch('sudo_on_chmod') else ''
    chown_sudo = 'sudo ' if fetch('sudo_on_chown') else ''

    def change_owner(owner_triple):
        """
        Changes unix owner/mode
        """

        run(chmod_sudo + 'chmod 0755 ' + entity_path)
        run(chown_sudo + 'chown %s:%s %s' % owner_triple)

    # 1) Create file/directory

    if entity_type == 'file':
        run('touch %s' % entity_path)
    else:
        run('mkdir -p %s' % entity_path)

    # 2) Change owner/mode

    if protected:
        protected_owner_user = fetch('protected_owner_user')
        protected_owner_group = fetch('protected_owner_group')

        change_owner(
            (protected_owner_user, protected_owner_group, entity_path))
    else:
        owner_user = fetch('owner_user', default_value=False)
        owner_group = fetch('owner_group', default_value=False)

        if owner_user != False and owner_group != False:
            change_owner((owner_user, owner_group, entity_path))
        else:
            run(chmod_sudo + 'chmod 0755 ' + entity_path)
コード例 #23
0
ファイル: deploy.py プロジェクト: py-mina-deploy/py-mina
def link_shared_paths():
    """
    Links shared paths to build folder
    """

    global build_to
    build_to = fetch('build_to')

    global shared
    shared = fetch('shared_path')

    def link_dirs(dirs):
        global shared
        global build_to

        for sdir in dirs:
            relative_path = '/'.join(['.', sdir])
            directory, filename_ = os.path.split(relative_path)
            shared_path = '/'.join([shared, sdir])

            with cd(build_to):
                create_entity(directory,
                              entity_type='directory',
                              protected=False)  # create parent directory
                run('rm -rf %s' % relative_path
                    )  # remove directory if it conficts with shared
                run('ln -s %s %s' %
                    (shared_path,
                     relative_path))  # link shared to current folder

    def link_files(files):
        global shared
        global build_to

        for sfile in files:
            relative_path = '/'.join(['.', sfile])
            directory, filename_ = os.path.split(relative_path)
            shared_path = '/'.join([shared, sfile])

            with cd(build_to):
                create_entity(directory,
                              entity_type='directory',
                              protected=False)  # create parent directory
                run('ln -sf %s %s' %
                    (shared_path,
                     relative_path))  # link shared to current folder

    shared_dirs = fetch('shared_dirs', default_value=[])
    shared_files = fetch('shared_files', default_value=[])
    any_shared_dir = len(shared_dirs) > 0
    any_shared_file = len(shared_files) > 0

    protected_shared_dirs = fetch('protected_shared_dirs', default_value=[])
    protected_shared_files = fetch('protected_shared_files', default_value=[])
    any_protected_shared_dir = len(protected_shared_dirs) > 0
    any_protected_shared_file = len(protected_shared_files) > 0

    if any_shared_dir or any_shared_file or any_protected_shared_dir or any_protected_shared_file:
        echo_subtask("Linking shared paths")

        if any_shared_dir: link_dirs(shared_dirs)
        if any_shared_file: link_files(shared_files)

        if any_protected_shared_dir: link_dirs(protected_shared_dirs)
        if any_protected_shared_file: link_files(protected_shared_files)