Commits (41)
...@@ -9,11 +9,11 @@ health-check: ...@@ -9,11 +9,11 @@ health-check:
- fab --version - fab --version
- fab -f . --list-format=nested --list - fab -f . --list-format=nested --list
tags: tags:
- docker-images - docker-generic
sonarqube: sonarqube:
image: ntdt/sonar-scanner:2.7 image: ntdt/sonar-scanner:2.7
stage: quality stage: quality
script: script:
- cd $CI_PROJECT_DIR && /opt/sonar-scanner/bin/sonar-scanner -Dsonar.host.url=$SONAR_HOST -Dsonar.login=$SONAR_TOKEN - cd $CI_PROJECT_DIR && /opt/sonar-scanner/bin/sonar-scanner -Dsonar.host.url=$SONAR_HOST -Dsonar.login=$SONAR_TOKEN
tags: tags:
- docker-images - docker-generic
...@@ -10,12 +10,15 @@ This project adheres to http://semver.org/[Semantic Versioning]. ...@@ -10,12 +10,15 @@ This project adheres to http://semver.org/[Semantic Versioning].
=== Fixed === Fixed
* Use Fabric built-in *always_use_pty* variable to set interactive mode
* Site name can now have whitespaces without breaking the shell execution string * Site name can now have whitespaces without breaking the shell execution string
* Add a new variable in conf file to select one or more languages (PO files) when building sites. Default: _fr_.
=== Added === Added
* Add a Patternlab command to build the static style guide: `fab patternlab.build`. * Add a Patternlab command to build the static style guide: `fab patternlab.build`.
* Add a Git command to verify repositories states and warn user if changes might be lost. * Add a Git command to verify repositories states and warn user if changes might be lost.
* Add a docker.clean command to clean docker's workspace (removes container and image).
== 2.0.0 - 2016/05/09 == 2.0.0 - 2016/05/09
......
...@@ -35,9 +35,6 @@ Those are global project parameters mandatory to Drupalizer. ...@@ -35,9 +35,6 @@ Those are global project parameters mandatory to Drupalizer.
|This env var is defined by Fabric itself, and it's defaut value is True. |This env var is defined by Fabric itself, and it's defaut value is True.
|You can easily pass it to False, addinf --no-pty to your fab command line. Useful in Jenkins jobs. |You can easily pass it to False, addinf --no-pty to your fab command line. Useful in Jenkins jobs.
|_locale_
|If True, install the site in French.
|=== |===
=== Site settings === Site settings
...@@ -60,6 +57,9 @@ Those are global project parameters mandatory to Drupalizer. ...@@ -60,6 +57,9 @@ Those are global project parameters mandatory to Drupalizer.
|_site_profile_repo_ |_site_profile_repo_
|The installation profile git repository, if applicable. |The installation profile git repository, if applicable.
|_site_profile_branch_
|Branch you want to use to access to site makefile.
|_site_profile_makefile_ |_site_profile_makefile_
|The Drush Makefile to run to build the platform. |The Drush Makefile to run to build the platform.
...@@ -88,7 +88,7 @@ Those are global project parameters mandatory to Drupalizer. ...@@ -88,7 +88,7 @@ Those are global project parameters mandatory to Drupalizer.
|The Drupal site directory (only for multisite). Default: _default_. |The Drupal site directory (only for multisite). Default: _default_.
|_site_languages_ |_site_languages_
|Translation files you need to download when building new Drupal installation (separate with comma). Default: _fr_. |Translation files that must be downloaded when building Drupal and activated during installation (separate with comma). Default: _fr_.
|=== |===
......
from fabric.api import task, env, execute
from fabric.colors import red
from fabric.contrib.console import confirm
import behat
import deploy
import docker import docker
from deploy import *
import drush import drush
import behat
import patternlab import patternlab
from .environments import e
from fabric.api import task, env, execute from .environments import e
from deploy import migrate, provision, push
from fabric.colors import red
from fabric.contrib.console import confirm
@task @task
def init(): def init():
""" """
Complete local installation process, used generally when building the docker image for install and configure Drupal. Complete local installation process, used generally when building the docker image for install and configure Drupal.
""" """
execute(docker.image_create) execute(docker.image_create)
execute(docker.container_start) execute(docker.container_start)
execute(drush.make, 'install') execute(drush.make, 'install')
execute(drush.site_install, host='root@{}'.format(env.container_ip)) execute(drush.site_install, host='root@{}'.format(env.container_ip))
execute(drush.aliases) execute(drush.aliases)
execute(behat.init, host='root@{}'.format(env.container_ip))
@task
def test(tags=''):
"""
Setup Behat and run the complete tests suite. Default output formatters: pretty and JUnit.
The JUnit report file is specified in the Behat configuration file. Default: tests/behat/out/behat.junit.xml.
:param tags Specific Behat tests tags to run.
"""
execute(behat.init)
if not tags:
execute(behat.run)
else:
execute(behat.run, tags='{}'.format(tags))
execute(behat.init, host='root@{}'.format(env.container_ip))
@task @task
def install(): def install():
""" """
Run the full installation process. Run the full installation process.
""" """
execute(drush.make, 'install') execute(drush.make, 'install')
execute(drush.site_install) execute(drush.site_install)
execute(behat.init) execute(behat.init)
@task @task
def update(): def release():
""" """
Update the full codebase and run the availabe database updates. Generate all artefacts related to a release process or a deployment process.
""" """
execute(drush.archive_dump)
execute(drush.make, 'update') execute(drush.gen_doc)
execute(drush.updatedb)
execute(behat.init)
@task @task
def release(): def test(tags=''):
""" """
Generate all artefacts related to a release process or a deployment process. Setup Behat and run the complete tests suite. Default output formatters: pretty and JUnit.
The JUnit report file is specified in the Behat configuration file. Default: tests/behat/out/behat.junit.xml.
:param tags Specific Behat tests tags to run.
""" """
execute(behat.init)
execute(drush.archive_dump) if not tags:
execute(drush.gen_doc) execute(behat.run)
else:
execute(behat.run, tags='{}'.format(tags))
@task @task
def deploy(environment): def update():
"""Deploy code and run database updates on a target Drupal environment.
""" """
Update the full codebase and run the availabe database updates.
execute(provision, environment) """
execute(push, environment, hosts=env.hosts) execute(drush.make, 'update')
execute(migrate, environment, hosts=env.hosts) execute(drush.updatedb)
execute(behat.init)
from __future__ import unicode_literals from __future__ import unicode_literals
from fabric.api import task, roles, env from fabric.api import task, roles, env
from fabric.colors import green from fabric.colors import green
import helpers as h import helpers as h
@task @task
@roles('docker') @roles('docker')
def init(rewrite=True): def init(rewrite=True):
...@@ -12,7 +14,6 @@ def init(rewrite=True): ...@@ -12,7 +14,6 @@ def init(rewrite=True):
:param role Default 'role' where to run the task :param role Default 'role' where to run the task
:param rewrite If the behat.yml file should be rewrited or not. :param rewrite If the behat.yml file should be rewrited or not.
""" """
role = 'docker' role = 'docker'
workspace = env.docker_workspace workspace = env.docker_workspace
host = env.site_hostname host = env.site_hostname
...@@ -24,18 +25,18 @@ def init(rewrite=True): ...@@ -24,18 +25,18 @@ def init(rewrite=True):
h.fab_run(role, 'sed -i "s@%DRUPAL_ROOT@{}@g" behat.yml'.format(site_root)) h.fab_run(role, 'sed -i "s@%DRUPAL_ROOT@{}@g" behat.yml'.format(site_root))
h.fab_run(role, 'sed -i "s@%URL@http://{}@g" behat.yml'.format(host)) h.fab_run(role, 'sed -i "s@%URL@http://{}@g" behat.yml'.format(host))
h.fab_run(role, 'echo "127.0.0.1 {}" >> /etc/hosts'.format(host)) h.fab_run(role, 'echo "127.0.0.1 {}" >> /etc/hosts'.format(host))
print green('Behat is now properly configured. The configuration file is {}/tests/behat/behat.yml'.format(workspace)) print green('Behat is now properly configured. The configuration file is {}/tests/behat/behat.yml'.format(workspace))
else: else:
print green('{}/tests/behat/behat.yml is already created.'.format(workspace)) print green('{}/tests/behat/behat.yml is already created.'.format(workspace))
@task() @task
@roles('docker') @roles('docker')
def install(): def install():
""" """
Install behat Install behat
""" """
role = 'docker' role = 'docker'
workspace = env.docker_workspace workspace = env.docker_workspace
...@@ -44,6 +45,7 @@ def install(): ...@@ -44,6 +45,7 @@ def install():
h.fab_run(role, 'curl -s https://getcomposer.org/installer | php') h.fab_run(role, 'curl -s https://getcomposer.org/installer | php')
h.fab_run(role, 'php composer.phar install') h.fab_run(role, 'php composer.phar install')
h.fab_run(role, 'ln -s bin/behat /usr/local/bin/behat') h.fab_run(role, 'ln -s bin/behat /usr/local/bin/behat')
print green('Behat has been properly installed with Composer in /usr/local/bin') print green('Behat has been properly installed with Composer in /usr/local/bin')
else: else:
print(green('Behat is already installed, no need for a new installation')) print(green('Behat is already installed, no need for a new installation'))
...@@ -56,7 +58,6 @@ def run(tags='~@wip&&~@disabled&&~@test'): ...@@ -56,7 +58,6 @@ def run(tags='~@wip&&~@disabled&&~@test'):
Execute the complete Behat tests suite. Execute the complete Behat tests suite.
:param role Default 'role' where to run the task :param role Default 'role' where to run the task
""" """
role = 'docker' role = 'docker'
workspace = env.docker_workspace workspace = env.docker_workspace
...@@ -64,9 +65,10 @@ def run(tags='~@wip&&~@disabled&&~@test'): ...@@ -64,9 +65,10 @@ def run(tags='~@wip&&~@disabled&&~@test'):
# In the container behat is installed globaly, so check before install it inside the tests directory # In the container behat is installed globaly, so check before install it inside the tests directory
if not h.fab_exists(role, '/usr/local/bin/behat') or not h.fab_exists(role, '../tests/behat/bin/behat'): if not h.fab_exists(role, '/usr/local/bin/behat') or not h.fab_exists(role, '../tests/behat/bin/behat'):
install() install()
# If the configuration file behat.yml doesn't exist, call behat_init before run the test. # If the configuration file behat.yml doesn't exist, call behat_init before run the test.
if not h.fab_exists(role, '{}/tests/behat/behat.yml'.format(workspace)): if not h.fab_exists(role, '{}/tests/behat/behat.yml'.format(workspace)):
init() init()
with h.fab_cd(role, '{}/tests/behat'.format(workspace)): with h.fab_cd(role, '{}/tests/behat'.format(workspace)):
h.fab_run(role, 'behat --format junit --format pretty --tags "{}" --colors'.format(tags)) h.fab_run(role, 'behat --format junit --format pretty --tags "{}" --colors'.format(tags))
from __future__ import unicode_literals from __future__ import unicode_literals
from fabric.api import task, roles, env from fabric.api import task, roles, env
from fabric.colors import red, green from fabric.colors import red, green
import helpers as h import helpers as h
@task @task
@roles('docker') @roles('docker')
def db_import(filename, role='docker'): def db_import(filename, role='docker'):
...@@ -13,7 +15,6 @@ def db_import(filename, role='docker'): ...@@ -13,7 +15,6 @@ def db_import(filename, role='docker'):
:param filename: a full path to a gzipped sql dump. :param filename: a full path to a gzipped sql dump.
""" """
if h.fab_exists(role, filename): if h.fab_exists(role, filename):
print green('Database dump {} found.'.format(filename)) print green('Database dump {} found.'.format(filename))
h.fab_run(role, 'zcat {} | mysql -u{} -p{} {}'.format(filename, env.site_db_user, env.site_db_pass, env.site_db_name)) h.fab_run(role, 'zcat {} | mysql -u{} -p{} {}'.format(filename, env.site_db_user, env.site_db_pass, env.site_db_name))
......
...@@ -5,34 +5,34 @@ from fabric.api import env ...@@ -5,34 +5,34 @@ from fabric.api import env
# Project settings # Project settings
env.project_name = '' env.project_name = 'drupalizer-default'
env.workspace = path.join(path.dirname(__file__), path.pardir) env.workspace = path.join(path.dirname(__file__), path.pardir)
env.locale = False
# Site # Site
env.site_root = '{}/src/drupal'.format(env.workspace) env.site_root = '{}/src/drupal'.format(env.workspace)
env.site_name = '' env.site_name = 'Default Drupalizer'
env.site_environment = 'local' env.site_environment = 'local'
env.site_profile = '' env.site_profile = 'standard'
env.site_profile_repo = '' env.site_profile_repo = ''
env.site_profile_makefile = '' env.site_profile_makefile = 'drupalizer.make'
env.site_profile_branch= '7.x' env.site_profile_branch= '7.x'
env.site_db_user = 'dev' env.site_db_user = 'dev'
env.site_db_pass = 'dev' env.site_db_pass = 'dev'
env.site_db_host = 'localhost' env.site_db_host = 'localhost'
env.site_db_name = '' env.site_db_name = 'dev'
env.site_hostname = '' env.site_hostname = 'drupalizer.dev.local'
env.site_admin_user = 'admin' env.site_admin_user = 'admin'
env.site_admin_pass = 'admin' env.site_admin_pass = 'admin'
env.site_subdir = 'default' env.site_subdir = 'default'
env.site_languages = 'fr' env.site_languages = ''
# PatternLab # PatternLab
# Specify the PatternLab dir is you want the style guide to be generated # Specify the PatternLab dir is you want the style guide to be generated
env.patternlab_dir = '' env.patternlab_dir = ''
...@@ -41,6 +41,7 @@ env.patternlab_dir = '' ...@@ -41,6 +41,7 @@ env.patternlab_dir = ''
env.db_dump = False env.db_dump = False
# Docker # Docker
env.docker_workspace = '/opt/sfl' env.docker_workspace = '/opt/sfl'
...@@ -49,13 +50,17 @@ env.bind_port = 8001 ...@@ -49,13 +50,17 @@ env.bind_port = 8001
env.apache_user = 'www-data' env.apache_user = 'www-data'
# Docker auto-added container IP # Docker auto-added container IP
env.container_ip = '172.17.0.0'
env.container_ip = '172.17.0.2'
# Hook commands # Hook commands
# Example:
# env.hook_post_install = ['drush fra -y', 'drush cc all']
# env.hook_post_update = ['drush fra -y', 'drush cc all']
env.hook_post_install = ['drush fra -y', 'drush cc all'] env.hook_post_install = []
env.hook_post_update = ['drush fra -y', 'drush cc all'] env.hook_post_update = []
# Target environments definition # Target environments definition
......
...@@ -17,13 +17,15 @@ ...@@ -17,13 +17,15 @@
# #
from __future__ import unicode_literals from __future__ import unicode_literals
from fabric.api import task, env, local, run
import glob
import os
from fabric.api import task, env, local, run, execute, lcd
from fabric.colors import green from fabric.colors import green
from fabric.utils import abort from fabric.utils import abort
import helpers as h import helpers as h
import os
import glob
def _set_hosts(environment): def _set_hosts(environment):
...@@ -51,7 +53,9 @@ def _aegir_platform_name(target, environment): ...@@ -51,7 +53,9 @@ def _aegir_platform_name(target, environment):
""" """
if 'aegir_platform' not in target: if 'aegir_platform' not in target:
abort('Aegir needs a unique platform name to function properly. Check your aegir_platform key in your aliases.') abort('Aegir needs a unique platform name to function properly. Check your aegir_platform key in your aliases.')
aegir_platform = target.get('aegir_platform') aegir_platform = target.get('aegir_platform')
return aegir_platform.format(name=env.project_name, env=environment, build=env.build_number) return aegir_platform.format(name=env.project_name, env=environment, build=env.build_number)
...@@ -61,8 +65,10 @@ def _target_dir(environment): ...@@ -61,8 +65,10 @@ def _target_dir(environment):
:param environment :param environment
""" """
target = env.aliases.get(environment) target = env.aliases.get(environment)
if _is_aegir_deployment(target): if _is_aegir_deployment(target):
return target.get('root') + _aegir_platform_name(target, environment) return target.get('root') + _aegir_platform_name(target, environment)
return target.get('root') return target.get('root')
...@@ -98,7 +104,6 @@ def _clear_site_cache(target, environment): ...@@ -98,7 +104,6 @@ def _clear_site_cache(target, environment):
Helper function to clear site cache. Helper function to clear site cache.
:param environment :param environment
""" """
run('drush --yes --root={} cache-clear all'.format(target.get('root'))) run('drush --yes --root={} cache-clear all'.format(target.get('root')))
print(green('The cache have been cleared on the target environment {}.'.format(environment))) print(green('The cache have been cleared on the target environment {}.'.format(environment)))
...@@ -109,10 +114,13 @@ def _get_archive_from_dir(directory): ...@@ -109,10 +114,13 @@ def _get_archive_from_dir(directory):
:param directory The directory used to untar the artefact. :param directory The directory used to untar the artefact.
""" """
files = glob.glob1(directory, '*.tar.gz') files = glob.glob1(directory, '*.tar.gz')
if len(files) == 0: if len(files) == 0:
abort('No tarball found in {}'.format(directory)) abort('No tarball found in {}'.format(directory))
if len(files) > 1: if len(files) > 1:
abort('More than one tarball has been found in {}. Can not decide which one to deploy.'.format(directory)) abort('More than one tarball has been found in {}. Can not decide which one to deploy.'.format(directory))
return files[0] return files[0]
...@@ -120,7 +128,7 @@ def _rsync_platform(target, target_directory): ...@@ -120,7 +128,7 @@ def _rsync_platform(target, target_directory):
""" """
Helper function to rsync platform to server. Helper function to rsync platform to server.
""" """
local('rsync -a src/drupal/ {}@{}:{}'.format(target.get('user'), target.get('host'), target_directory)) local('rsync -a --exclude sites/*/settings.php --exclude sites/*/files src/drupal/ {}@{}:{}'.format(target.get('user'), target.get('host'), target_directory))
def _aegir_provision_platform(platform, aegir_path, aegir_destsrv): def _aegir_provision_platform(platform, aegir_path, aegir_destsrv):
...@@ -132,6 +140,7 @@ def _aegir_provision_platform(platform, aegir_path, aegir_destsrv): ...@@ -132,6 +140,7 @@ def _aegir_provision_platform(platform, aegir_path, aegir_destsrv):
""" """
run('drush --root="{}/platforms/{}" provision-save "@platform_{}" --context_type="platform" --web_server=@{}' run('drush --root="{}/platforms/{}" provision-save "@platform_{}" --context_type="platform" --web_server=@{}'
.format(aegir_path, platform, platform, aegir_destsrv)) .format(aegir_path, platform, platform, aegir_destsrv))
run('drush @hostmaster hosting-import platform_{}'.format(platform)) run('drush @hostmaster hosting-import platform_{}'.format(platform))
run('drush @hostmaster hosting-dispatch') run('drush @hostmaster hosting-dispatch')
...@@ -156,28 +165,36 @@ def _aegir_remove_platform_without_sites(target, environment, platform): ...@@ -156,28 +165,36 @@ def _aegir_remove_platform_without_sites(target, environment, platform):
run('{}/remove-platforms {} {}'.format(aegir_path, environment, platform)) run('{}/remove-platforms {} {}'.format(aegir_path, environment, platform))
@task(default=True)
def deploy(environment):
"""Deploy code and run database updates on a target Drupal environment.
"""
execute(provision, environment)
execute(push, environment, hosts=env.hosts)
execute(migrate, environment, hosts=env.hosts)
@task @task
def provision(environment, role='local'): def provision(environment):
""" """
Provision a Jenkins deployment. Provision a Jenkins deployment.
This task loads the target environment and extract the archive to deploy. This task loads the target environment and extract the archive to deploy.
:param environment The environment to deploy the site DEV, STAGE, PROD :param environment The environment to deploy the site DEV, STAGE, PROD
:param role Tha fabric role to run the task.
""" """
_set_hosts(environment) _set_hosts(environment)
artefact = _get_archive_from_dir(env.builddir) artefact = _get_archive_from_dir(env.builddir)
with h.fab_cd(role, '{}/src'.format(env.workspace)): with lcd('{}/src'.format(env.workspace)):
# Clear the currently installed platform # Clear the currently installed platform
if h.fab_exists(role, env.site_root): if os.path.exists(env.site_root):
h.fab_run(role, 'rm -rf {}'.format(env.site_root)) local('rm -rf {}'.format(env.site_root))
# Extract the platform to deploy # Extract the platform to deploy
h.fab_run(role, 'tar -xzf {}/{}'.format(env.builddir, artefact)) local('tar -xzf {}/{}'.format(env.builddir, artefact))
# Fast-check if the archive looks like a Drupal installation # Fast-check if the archive looks like a Drupal installation
if not h.fab_exists(role, '{}/src/drupal'.format(env.workspace)): if not os.path.exists('{}/src/drupal'.format(env.workspace)):
abort('The archive to deploy does not contain a drupal directory.') abort('The archive to deploy does not contain a drupal directory.')
if not os.path.isfile('{}/src/drupal/cron.php'.format(env.workspace)): if not os.path.isfile('{}/src/drupal/cron.php'.format(env.workspace)):
...@@ -186,12 +203,11 @@ def provision(environment, role='local'): ...@@ -186,12 +203,11 @@ def provision(environment, role='local'):
print(green('The platform {} is now ready to be deployed to the target environment {}.'.format(artefact, print(green('The platform {} is now ready to be deployed to the target environment {}.'.format(artefact,
environment))) environment)))
@task @task
def push(environment): def push(environment):
""" """
Push the platform to the target environment. Push the platform to the target environment.
:param environment: The target environment. It must match a valid Drush alias. :param environment: The target environment. It must match a valid Drush alias.
""" """
target = env.aliases.get(environment) target = env.aliases.get(environment)
target_directory = _target_dir(environment) target_directory = _target_dir(environment)
...@@ -217,6 +233,7 @@ def migrate(environment): ...@@ -217,6 +233,7 @@ def migrate(environment):
if _is_aegir_deployment(target): if _is_aegir_deployment(target):
# Deploy to Aegir server. # Deploy to Aegir server.
platform = _aegir_platform_name(target, environment) platform = _aegir_platform_name(target, environment)
if env.get('migrate', "false") == "true": if env.get('migrate', "false") == "true":
_aegir_migrate_sites(target, environment, platform) _aegir_migrate_sites(target, environment, platform)
......
from __future__ import unicode_literals from __future__ import unicode_literals
from fabric.api import task, roles, env, local, run
from fabric.api import task, roles, env, local, run, lcd, execute
from fabric.colors import red, green from fabric.colors import red, green
from fabric.contrib.console import confirm
import helpers as h import helpers as h
########################################################### ###########################################################
# Helper functions to manage docker images and containers # # Helper functions to manage docker images and containers #
########################################################### ###########################################################
def docker_ps(running_only=False): def docker_ps(running_only=False):
args = '' if running_only else '-a' args = '' if running_only else '-a'
result = local('docker ps %s' % args, capture=True) result = local('docker ps %s' % args, capture=True)
...@@ -22,9 +26,11 @@ def docker_tryrun(imgname, containername=None, opts='', mounts=None, cmd='', res ...@@ -22,9 +26,11 @@ def docker_tryrun(imgname, containername=None, opts='', mounts=None, cmd='', res
# Returns True if the container was effectively ran (false if it was restarted or aborted) # Returns True if the container was effectively ran (false if it was restarted or aborted)
if not mounts: if not mounts:
mounts = [] mounts = []
if containername and containername in docker_ps(running_only=True): if containername and containername in docker_ps(running_only=True):
print green("%s already running" % containername) print green("%s already running" % containername)
return False return False
if containername and containername in docker_ps(running_only=False): if containername and containername in docker_ps(running_only=False):
if restart: if restart:
print green("%s already exists and is stopped. Restarting!" % containername) print green("%s already exists and is stopped. Restarting!" % containername)
...@@ -34,16 +40,20 @@ def docker_tryrun(imgname, containername=None, opts='', mounts=None, cmd='', res ...@@ -34,16 +40,20 @@ def docker_tryrun(imgname, containername=None, opts='', mounts=None, cmd='', res
print red("There's a dangling container %s! That's not supposed to happen. Aborting" % containername) print red("There's a dangling container %s! That's not supposed to happen. Aborting" % containername)
print "Run 'docker rm %s' to remove that container" % containername print "Run 'docker rm %s' to remove that container" % containername
return False return False
for from_path, to_path, canwrite in mounts: for from_path, to_path, canwrite in mounts:
abspath = from_path abspath = from_path
opt = ' -v %s:%s' % (abspath, to_path) opt = ' -v %s:%s' % (abspath, to_path)
if not canwrite: if not canwrite:
opt += ':ro' opt += ':ro'
opts += opt opts += opt
if containername: if containername:
containername_opt = '--name %s' % containername containername_opt = '--name %s' % containername
else: else:
containername_opt = '' containername_opt = ''
local('docker run %s %s %s %s' % (opts, containername_opt, imgname, cmd)) local('docker run %s %s %s %s' % (opts, containername_opt, imgname, cmd))
return True return True
...@@ -70,8 +80,10 @@ def docker_ensure_data_container(containername, volume_paths=None, base_image='b ...@@ -70,8 +80,10 @@ def docker_ensure_data_container(containername, volume_paths=None, base_image='b
volume_args = ' '.join('-v %s' % volpath for volpath in volume_paths) volume_args = ' '.join('-v %s' % volpath for volpath in volume_paths)
else: else:
volume_args = '' volume_args = ''
local('docker create %s --name %s %s' % (volume_args, containername, base_image)) local('docker create %s --name %s %s' % (volume_args, containername, base_image))
return True return True
return False return False
...@@ -86,69 +98,66 @@ def docker_isrunning(containername): ...@@ -86,69 +98,66 @@ def docker_isrunning(containername):
def docker_images(): def docker_images():
result = local('docker images', capture=True) result = local('docker images', capture=True)
lines = result.stdout.splitlines() lines = result.stdout.splitlines()
# image name is supposed to be the first column # image name is supposed to be the first column
assert lines[0].strip().startswith('REPOSITORY') assert lines[0].strip().startswith('REPOSITORY')
return [line.strip().split(' ')[0] for line in lines] return [line.strip().split(' ')[0] for line in lines]
@task @task
@roles('local') @roles('local')
def connect(role='local'): def connect():
""" """
Connect to a docker container using "docker -it exec <name> bash". Connect to a docker container using "docker -it exec <name> bash".
This is a better way to connect to the container than using ssh' This is a better way to connect to the container than using ssh'
:param role Default 'role' where to run the task
""" """
with h.fab_cd(role, env.workspace): with lcd(env.workspace):
if docker_isrunning('{}_container'.format(env.project_name)): if docker_isrunning('{}_container'.format(env.project_name)):
h.fab_run(role, 'docker exec -it {}_container bash'.format(env.project_name)) local('docker exec -it {}_container bash'.format(env.project_name))
else: else:
print(red('Docker container {}_container is not running, it should be running to be able to connect.')) print(red('Docker container {}_container is not running, it should be running to be able to connect.'))
@task @task
@roles('local') @roles('local')
def image_create(role='local'): def image_create():
""" """
Create docker images Create docker images
:param role Default 'role' where to run the task
""" """
with lcd(env.workspace):
with h.fab_cd(role, env.workspace):
if '{}/drupal'.format(env.project_name) in docker_images(): if '{}/drupal'.format(env.project_name) in docker_images():
print(red('Docker image {}/drupal was found, you has already build this image'.format(env.project_name))) print(red('Docker image {}/drupal was found, you has already build this image'.format(env.project_name)))
else: else:
h.copy_public_ssh_keys(role) h.copy_public_ssh_keys('local')
h.fab_run(role, 'docker build -t {}/drupal .'.format(env.project_name)) local('docker build -t {}/drupal .'.format(env.project_name))
print(green('Docker image {}/drupal was build successful'.format(env.project_name))) print(green('Docker image {}/drupal was build successful'.format(env.project_name)))
@task @task
@roles('local') @roles('local')
def container_start(role='local'): def container_start():
""" """
Run docker containers Run docker containers
:param role Default 'role' where to run the task
""" """
with h.fab_cd(role, env.workspace): with lcd(env.workspace):
if '{}/drupal'.format(env.project_name) in docker_images(): if '{}/drupal'.format(env.project_name) in docker_images():
if docker_tryrun('{}/drupal'.format(env.project_name), if docker_tryrun('{}/drupal'.format(env.project_name),
'{}_container'.format(env.project_name), '{}_container'.format(env.project_name),
'-d -p {}:80'.format(env.bind_port), '-d -p {}:80'.format(env.bind_port),
mounts=[(env.workspace, env.docker_workspace, True)]): mounts=[(env.workspace, env.docker_workspace, True)]):
# If container was successful build, get the IP address and show it to the user. # If container was successful build, get the IP address and show it to the user.
env.container_ip = h.fab_run(role, 'docker inspect -f "{{{{.NetworkSettings.IPAddress}}}}" ' env.container_ip = local('docker inspect -f "{{{{.NetworkSettings.IPAddress}}}}" '
'{}_container'.format(env.project_name), capture=True) '{}_container'.format(env.project_name), capture=True)
if env.get('always_use_pty', True): if env.get('always_use_pty', True):
h.fab_update_hosts(env.container_ip, env.site_hostname) h.fab_update_hosts(env.container_ip, env.site_hostname)
print(green('Docker container {}_container was build successful. ' print(green('Docker container {}_container was build successful. '
'To visit the Website open a web browser in http://{} or ' 'To visit the Website open a web browser in http://{} or '
'http://localhost:{}.'.format(env.project_name, env.site_hostname, env.bind_port))) 'http://localhost:{}.'.format(env.project_name, env.site_hostname, env.bind_port)))
h.fab_update_container_ip(env.container_ip) h.fab_update_container_ip(env.container_ip)
else: else:
print(red('Docker image {}/drupal not found and is a requirement to run the {}_container.' print(red('Docker image {}/drupal not found and is a requirement to run the {}_container.'
'Please, run first "fab create" in order to build the {}/drupal ' 'Please, run first "fab create" in order to build the {}/drupal '
...@@ -157,16 +166,16 @@ def container_start(role='local'): ...@@ -157,16 +166,16 @@ def container_start(role='local'):
@task @task
@roles('local') @roles('local')
def container_stop(role='local'): def container_stop():
""" """
Stop docker containers Stop docker containers
:param role Default 'role' where to run the task
""" """
with h.fab_cd(role, env.workspace): with lcd(env.workspace):
if '{}_container'.format(env.project_name) in docker_ps(): if '{}_container'.format(env.project_name) in docker_ps():
if env.get('always_use_pty', True): if env.get('always_use_pty', True):
h.fab_remove_from_hosts(env.site_hostname) h.fab_remove_from_hosts(env.site_hostname)
h.fab_run(role, 'docker stop {}_container'.format(env.project_name))
local('docker stop {}_container'.format(env.project_name))
print(green('Docker container {}_container was successful stopped'.format(env.project_name))) print(green('Docker container {}_container was successful stopped'.format(env.project_name)))
else: else:
print(red('Docker container {}_container was not running or paused'.format(env.project_name))) print(red('Docker container {}_container was not running or paused'.format(env.project_name)))
...@@ -174,55 +183,69 @@ def container_stop(role='local'): ...@@ -174,55 +183,69 @@ def container_stop(role='local'):
@task @task
@roles('local') @roles('local')
def container_remove(role='local'): def container_remove():
""" """
Stop docker containers Stop docker containers
:param role Default 'role' where to run the task
""" """
with h.fab_cd(role, env.workspace): with lcd(env.workspace):
if '{}_container'.format(env.project_name) in docker_ps(): if '{}_container'.format(env.project_name) in docker_ps():
if env.get('always_use_pty', True): if env.get('always_use_pty', True):
h.fab_remove_from_hosts(env.site_hostname) h.fab_remove_from_hosts(env.site_hostname)
h.fab_run(role, 'docker rm -f {}_container'.format(env.project_name)) local('docker rm -f {}_container'.format(env.project_name))
print(green('Docker container {}_container was successful removed'.format(env.project_name))) print(green('Docker container {}_container was successful removed'.format(env.project_name)))
else: else:
print(red('Docker container {}_container was already removed'.format(env.project_name))) print(red('Docker container {}_container was already removed'.format(env.project_name)))
@task() @task
@roles('local') @roles('local')
def image_remove(role='local'): def image_remove():
""" """
Remove docker container and images Remove docker container and images
:param role Default 'role' where to run the task
""" """
with h.fab_cd(role, env.workspace): with lcd(env.workspace):
if docker_isrunning('{}_container'.format(env.project_name)): if docker_isrunning('{}_container'.format(env.project_name)):
print(red('Docker container {}_container is running, ' print(red('Docker container {}_container is running, '
'you should stopped it after remove the image {}/drupal'.format(env.project_name, 'you should stopped it after remove the image {}/drupal'.format(env.project_name,
env.project_name))) env.project_name)))
if '{}/drupal'.format(env.project_name) in docker_images(): if '{}/drupal'.format(env.project_name) in docker_images():
h.fab_run(role, 'docker rmi -f {}/drupal'.format(env.project_name)) local('docker rmi -f {}/drupal'.format(env.project_name))
# Remove dangling docker images to free space. # Remove dangling docker images to free space.
if '<none>' in docker_images(): if '<none>' in docker_images():
h.fab_run(role, 'docker images --filter="dangling=true" -q | xargs docker rmi -f') local('docker images --filter="dangling=true" -q | xargs docker rmi -f')
print(green('Docker image {}/drupal was successful removed'.format(env.project_name))) print(green('Docker image {}/drupal was successful removed'.format(env.project_name)))
else: else:
print(red('Docker image {}/drupal was not found'.format(env.project_name))) print(red('Docker image {}/drupal was not found'.format(env.project_name)))
@task
@roles('local')
def clean():
"""
Clean docker workspace (removes container & images)
"""
if (confirm(
red('This will stop, remove container and delete docker image ' +
'related to this project. Do you want to continue?'),
default=False)):
execute(container_stop)
execute(container_remove)
execute(image_remove)
@task @task
@roles('docker') @roles('docker')
def update_host(): def update_host():
""" """
Update hostname resolution in the container. Update hostname resolution in the container.
""" """
site_hostname = run("hostname") site_hostname = run("hostname")
run("sed '/{}/c\{} {} localhost.domainlocal' " run("sed '/{}/c\{} {} localhost.domainlocal' "
"/etc/hosts > /root/hosts.backup".format(env.container_ip, env.container_ip, site_hostname)) "/etc/hosts > /root/hosts.backup".format(env.container_ip, env.container_ip, site_hostname))
run("cat /root/hosts.backup > /etc/hosts") run("cat /root/hosts.backup > /etc/hosts")
h.fab_update_container_ip() h.fab_update_container_ip()
...@@ -17,17 +17,17 @@ ...@@ -17,17 +17,17 @@
# #
from __future__ import unicode_literals from __future__ import unicode_literals
from fabric.api import task, roles, env from datetime import datetime
from fabric.contrib.console import confirm
from fabric.api import task, roles, env, local
from fabric.colors import red, green from fabric.colors import red, green
from fabric.contrib.console import confirm
from fabric.utils import abort from fabric.utils import abort
from datetime import datetime
import helpers as h
import core as c import core as c
import helpers as h
from git import isGitDirty from git import is_git_dirty
@task(alias='make') @task(alias='make')
...@@ -36,9 +36,8 @@ def make(action='install'): ...@@ -36,9 +36,8 @@ def make(action='install'):
""" """
Build the platform by running the Makefile specified in the local_vars.py configuration file. Build the platform by running the Makefile specified in the local_vars.py configuration file.
""" """
if env.get('always_use_pty', True): if env.get('always_use_pty', True):
if (isGitDirty()): if (is_git_dirty()):
if (not confirm(red('There are warnings on status of your repositories. ' if (not confirm(red('There are warnings on status of your repositories. '
'Do you want to continue and reset all changes to remote repositories'' states?'), default=False)): 'Do you want to continue and reset all changes to remote repositories'' states?'), default=False)):
abort('Aborting "drush {}" since there might be a risk of loosing local data.'.format(action)) abort('Aborting "drush {}" since there might be a risk of loosing local data.'.format(action))
...@@ -47,21 +46,24 @@ def make(action='install'): ...@@ -47,21 +46,24 @@ def make(action='install'):
# Update profile codebase # Update profile codebase
if env.site_profile and env.site_profile != '' and not h.is_core_profile(env.site_profile): if env.site_profile and env.site_profile != '' and not h.is_core_profile(env.site_profile):
drush_opts += "--contrib-destination=profiles/{} ".format(env.site_profile)
h.update_profile() h.update_profile()
if not env.get('always_use_pty', True): if env.site_languages:
drush_opts += "--translations=" + env.site_languages + " " if not env.get('always_use_pty', True):
elif confirm(red('Say [Y] to {} the site at {} with the specified translation(s): {}. If you say [n] ' drush_opts += "--translations=" + env.site_languages + " "
'the site will be installed in English only'.format(action, env.site_root, env.site_languages))): elif confirm(red('Say [Y] to {} the site at {} with the specified translation(s): {}. If you say [n] '
drush_opts += "--translations=" + env.site_languages + " " 'the site will be installed in English only'.format(action, env.site_root, env.site_languages))):
drush_opts += "--translations=" + env.site_languages + " "
if env.get('always_use_pty', True): if env.get('always_use_pty', True):
drush_opts += " --working-copy --no-gitinfofile" drush_opts += " --working-copy --no-gitinfofile"
if not h.fab_exists('local', env.site_root): if not h.fab_exists('local', env.site_root):
h.fab_run('local', "mkdir {}".format(env.site_root)) local('mkdir {}'.format(env.site_root))
with h.fab_cd('local', env.site_root): with h.fab_cd('local', env.site_root):
h.fab_run('local', 'drush make {} {} -y'.format(drush_opts, env.makefile)) local('drush make {} {} -y'.format(drush_opts, env.makefile))
@task @task
...@@ -70,17 +72,18 @@ def aliases(): ...@@ -70,17 +72,18 @@ def aliases():
""" """
Copy conf/aliases.drushrc.php in the site environment. Copy conf/aliases.drushrc.php in the site environment.
""" """
role = 'docker' role = 'docker'
drush_aliases = env.site_drush_aliases drush_aliases = env.site_drush_aliases
workspace = env.docker_workspace workspace = env.docker_workspace
if not h.fab_exists(role, drush_aliases): if not h.fab_exists(role, drush_aliases):
h.fab_run(role, 'mkdir -p {}'.format(drush_aliases)) h.fab_run(role, 'mkdir -p {}'.format(drush_aliases))
with h.fab_cd(role, drush_aliases): with h.fab_cd(role, drush_aliases):
# Create aliases # Create aliases
if h.fab_exists(role, '{}/aliases.drushrc.php'.format(drush_aliases)): if h.fab_exists(role, '{}/aliases.drushrc.php'.format(drush_aliases)):
h.fab_run(role, 'rm {}/aliases.drushrc.php'.format(drush_aliases)) h.fab_run(role, 'rm {}/aliases.drushrc.php'.format(drush_aliases))
h.fab_run(role, 'cp {}/conf/aliases.drushrc.php .'.format(workspace)) h.fab_run(role, 'cp {}/conf/aliases.drushrc.php .'.format(workspace))
print(green('Drush aliases have been copied to {} directory.'.format(drush_aliases))) print(green('Drush aliases have been copied to {} directory.'.format(drush_aliases)))
...@@ -92,9 +95,7 @@ def updatedb(): ...@@ -92,9 +95,7 @@ def updatedb():
""" """
Run the available database updates. Similar to drush updatedb. Run the available database updates. Similar to drush updatedb.
""" """
role = 'docker' role = 'docker'
with h.fab_cd(role, env.docker_site_root): with h.fab_cd(role, env.docker_site_root):
h.fab_run(role, 'drush updatedb -y') h.fab_run(role, 'drush updatedb -y')
h.hook_execute(env.hook_post_update, role) h.hook_execute(env.hook_post_update, role)
...@@ -106,7 +107,6 @@ def site_install(): ...@@ -106,7 +107,6 @@ def site_install():
""" """
Run the site installation procedure. Run the site installation procedure.
""" """
role = 'docker' role = 'docker'
site_root = env.docker_site_root site_root = env.docker_site_root
apache = env.apache_user apache = env.apache_user
...@@ -127,7 +127,10 @@ def site_install(): ...@@ -127,7 +127,10 @@ def site_install():
h.fab_run(role, 'chown {}:{} ./sites'.format(env.apache_user, env.apache_user)) h.fab_run(role, 'chown {}:{} ./sites'.format(env.apache_user, env.apache_user))
h.fab_run(role, 'chmod ug+w ./sites/default'.format(env.docker_site_root)) h.fab_run(role, 'chmod ug+w ./sites/default'.format(env.docker_site_root))
locale = '--locale="fr"' if env.locale else '' if env.site_languages:
locale = '--locale="{}"'.format(env.site_languages.split(',')[0])
else:
locale = ''
h.fab_run(role, 'sudo -u {} drush site-install {} {} --db-url=mysql://{}:{}@{}/{} --site-name="{}" ' h.fab_run(role, 'sudo -u {} drush site-install {} {} --db-url=mysql://{}:{}@{}/{} --site-name="{}" '
'--account-name={} --account-pass={} --sites-subdir={} -y'.format(apache, profile, locale, '--account-name={} --account-pass={} --sites-subdir={} -y'.format(apache, profile, locale,
...@@ -153,18 +156,15 @@ def archive_dump(role='docker'): ...@@ -153,18 +156,15 @@ def archive_dump(role='docker'):
Archive the platform for release or deployment. Archive the platform for release or deployment.
:param role Default 'role' where to run the task :param role Default 'role' where to run the task
""" """
with h.fab_cd(role, env.docker_site_root): with h.fab_cd(role, env.docker_site_root):
platform = '{}-{}.tar.gz'.format(env.project_name, datetime.now().strftime('%Y%m%d_%H%M%S')) platform = '{}-{}.tar.gz'.format(env.project_name, datetime.now().strftime('%Y%m%d_%H%M%S'))
h.fab_run(role, 'rm -f {}/build/*.tar.gz'.format(env.docker_workspace)) h.fab_run(role, 'rm -f {}/build/*.tar.gz'.format(env.docker_workspace))
print(green('All tar.gz archives found in {}/build have been deleted.'.format(env.docker_workspace))) print(green('All tar.gz archives found in {}/build have been deleted.'.format(env.docker_workspace)))
h.fab_run( h.fab_run(role,
role, 'drush archive-dump --destination={}/build/{} --tags="sflinux {}" --generatorversion="2.x" '
'drush archive-dump --destination={}/build/{} --tags="sflinux {}" --generatorversion="2.x" ' '--generator="Drupalizer::fab drush.archive_dump" --tar-options="--exclude=.git"'
'--generator="Drupalizer::fab drush.archive_dump" --tar-options="--exclude=.git"' ''.format(env.docker_workspace, platform, env.project_name))
''.format(env.docker_workspace, platform, env.project_name)
)
@task @task
...@@ -174,13 +174,14 @@ def gen_doc(role='docker'): ...@@ -174,13 +174,14 @@ def gen_doc(role='docker'):
Generate README file Generate README file
:param role Default 'role' where to run the task :param role Default 'role' where to run the task
""" """
if h.fab_exists(role, '{}/README.adoc'.format(env.docker_workspace)): if h.fab_exists(role, '{}/README.adoc'.format(env.docker_workspace)):
h.fab_run(role, 'asciidoctor -d book -b html5 -o {}/README.html {}/README.adoc'. h.fab_run(role, 'asciidoctor -d book -b html5 -o {}/README.html {}/README.adoc'.
format(env.docker_workspace, env.docker_workspace)) format(env.docker_workspace, env.docker_workspace))
print(green('README.html generated in {}'.format(env.docker_workspace))) print(green('README.html generated in {}'.format(env.docker_workspace)))
if h.fab_exists(role, '{}/CHANGELOG.adoc'.format(env.docker_workspace)): if h.fab_exists(role, '{}/CHANGELOG.adoc'.format(env.docker_workspace)):
h.fab_run(role, 'asciidoctor -d book -b html5 -o {}/CHANGELOG.html {}/CHANGELOG.adoc'. h.fab_run(role, 'asciidoctor -d book -b html5 -o {}/CHANGELOG.html {}/CHANGELOG.adoc'.
format(env.docker_workspace, env.docker_workspace)) format(env.docker_workspace, env.docker_workspace))
print(green('CHANGELOG.html generated in {}'.format(env.docker_workspace))) print(green('CHANGELOG.html generated in {}'.format(env.docker_workspace)))
...@@ -2,6 +2,7 @@ from importlib import import_module ...@@ -2,6 +2,7 @@ from importlib import import_module
from fabric.utils import abort from fabric.utils import abort
def e(name): def e(name):
""" """
Set your environment before running other commands Set your environment before running other commands
......
import re
import time
from os import path from os import path
from fabric.api import task, env, execute
from fabric.api import task, env, local from fabric.api import task, env, local
from fabric.colors import red, green, yellow from fabric.colors import red, green, yellow
from fabric.api import task, env, execute
from fabric.contrib.console import confirm from fabric.contrib.console import confirm
from .environments import e
import helpers as h import helpers as h
import time
import re from .environments import e
@task(alias='is_dirty') @task(alias='is_dirty')
def check_status(): def check_status():
""" """
Check workspace's git repositories status. Check workspace's git repositories status.
""" """
if (is_git_dirty()):
if (isGitDirty()):
print red('Your workspace is not clean.') print red('Your workspace is not clean.')
else: else:
print green('Your workspace is clean.') print green('Your workspace is clean.')
def isGitDirty():
def is_git_dirty():
repos = local('find ' + path.normpath(env.workspace) + ' -name ".git"', capture=True).splitlines() repos = local('find ' + path.normpath(env.workspace) + ' -name ".git"', capture=True).splitlines()
nbWarnings = 0 nbWarnings = 0
for repo in repos: for repo in repos:
repoLocalPath = path.normpath(path.join(repo, '..')) repoLocalPath = path.normpath(path.join(repo, '..'))
nbWarnings += _checkRepo(repoLocalPath) nbWarnings += _check_repo(repoLocalPath)
return (nbWarnings > 0) return (nbWarnings > 0)
...@@ -39,7 +42,7 @@ def isGitDirty(): ...@@ -39,7 +42,7 @@ def isGitDirty():
# - attention aux conflits, faire un pull d'abord et valider la fusion automatique # - attention aux conflits, faire un pull d'abord et valider la fusion automatique
def _checkRepo(repoLocalPath): def _check_repo(repoLocalPath):
nbWarnings = 0 nbWarnings = 0
with h.fab_cd('local', repoLocalPath): with h.fab_cd('local', repoLocalPath):
print green('---') print green('---')
...@@ -47,21 +50,21 @@ def _checkRepo(repoLocalPath): ...@@ -47,21 +50,21 @@ def _checkRepo(repoLocalPath):
remoteName = local('git remote', capture=True) remoteName = local('git remote', capture=True)
filesStatusRawInfo = _getFilesStatusInformation() filesStatusRawInfo = _get_files_status_information()
print green('Verify local files status against current HEAD commit...') print green('Verify local files status against current HEAD commit...')
nbWarnings += _checkFilesStatusVsHeadCommit(filesStatusRawInfo) nbWarnings += _check_files_status_vs_head_commit(filesStatusRawInfo)
localBranchesRawInfo = _getLocalBranchesInformation() localBranchesRawInfo = _get_local_branches_information()
print green('Verify local branches exist on remote "' + remoteName + '"...'); print green('Verify local branches exist on remote "' + remoteName + '"...');
nbWarnings += _checkLocalBranchesExistOnRemote(localBranchesRawInfo, remoteName) nbWarnings += _check_local_branches_exist_on_remote(localBranchesRawInfo, remoteName)
print green('Verify branches status against remote...'); print green('Verify branches status against remote...');
nbWarnings += _checkLocalBranchesStatusVsRemote(localBranchesRawInfo, remoteName) nbWarnings += _check_local_branches_status_vs_remote(localBranchesRawInfo, remoteName)
return nbWarnings return nbWarnings
def _checkFilesStatusVsHeadCommit(filesStatusRawInfo): def _check_files_status_vs_head_commit(filesStatusRawInfo):
nbWarnings = 0 nbWarnings = 0
addableFiles = [] addableFiles = []
if (len(filesStatusRawInfo) > 0): if (len(filesStatusRawInfo) > 0):
...@@ -70,8 +73,10 @@ def _checkFilesStatusVsHeadCommit(filesStatusRawInfo): ...@@ -70,8 +73,10 @@ def _checkFilesStatusVsHeadCommit(filesStatusRawInfo):
# Break loop if filename is "fabfile" # Break loop if filename is "fabfile"
if fileStatusData[1] == 'fabfile': if fileStatusData[1] == 'fabfile':
break break
nbWarnings += 1 nbWarnings += 1
addableFiles.append(fileStatusData[1]) addableFiles.append(fileStatusData[1])
print yellow('File "' + fileStatusData[1] + '" ' + { print yellow('File "' + fileStatusData[1] + '" ' + {
'M': 'has un-commited modifications.', 'M': 'has un-commited modifications.',
'D': 'has been deleted.', 'D': 'has been deleted.',
...@@ -80,12 +85,13 @@ def _checkFilesStatusVsHeadCommit(filesStatusRawInfo): ...@@ -80,12 +85,13 @@ def _checkFilesStatusVsHeadCommit(filesStatusRawInfo):
return nbWarnings return nbWarnings
def _checkLocalBranchesExistOnRemote(localBranchesRawInfo, remoteName):
def _check_local_branches_exist_on_remote(localBranchesRawInfo, remoteName):
nbWarnings = 0 nbWarnings = 0
pushableBranches = [] pushableBranches = []
for localBranchRawInfo in localBranchesRawInfo: for localBranchRawInfo in localBranchesRawInfo:
localBranchName = _getBranchName(localBranchRawInfo) localBranchName = _get_branch_name(localBranchRawInfo)
if ((localBranchName is not None) and (not _remoteBranchExists(localBranchName))): if ((localBranchName is not None) and (not _remote_branch_exists(localBranchName))):
nbWarnings += 1 nbWarnings += 1
pushableBranches.append(localBranchName) pushableBranches.append(localBranchName)
print yellow('Local branch "' + localBranchName + '" is not present on "' + remoteName + '" remote.') print yellow('Local branch "' + localBranchName + '" is not present on "' + remoteName + '" remote.')
...@@ -95,12 +101,14 @@ def _checkLocalBranchesExistOnRemote(localBranchesRawInfo, remoteName): ...@@ -95,12 +101,14 @@ def _checkLocalBranchesExistOnRemote(localBranchesRawInfo, remoteName):
if (confirm(red('There are many local branches not present on remote. Do you want to sync theses?'), default=False)): if (confirm(red('There are many local branches not present on remote. Do you want to sync theses?'), default=False)):
for branchName in pushableBranches: for branchName in pushableBranches:
local('git push --set-upstream ' + remoteName + ' ' + branchName) local('git push --set-upstream ' + remoteName + ' ' + branchName)
# Do not alert with diff as local branches are now pushed # Do not alert with diff as local branches are now pushed
nbWarnings = 0 nbWarnings = 0
return nbWarnings return nbWarnings
def _checkLocalBranchesStatusVsRemote(localBranchesRawInfo, remoteName):
def _check_local_branches_status_vs_remote(localBranchesRawInfo, remoteName):
nbWarnings = 0 nbWarnings = 0
pushableBranches = [] pushableBranches = []
# on gere un git FR ou EN, a voir ce qu'on peut faire # on gere un git FR ou EN, a voir ce qu'on peut faire
...@@ -108,7 +116,7 @@ def _checkLocalBranchesStatusVsRemote(localBranchesRawInfo, remoteName): ...@@ -108,7 +116,7 @@ def _checkLocalBranchesStatusVsRemote(localBranchesRawInfo, remoteName):
pattern = re.compile('.*\[.* (ahead|en avance de) .*\].*') pattern = re.compile('.*\[.* (ahead|en avance de) .*\].*')
for localBranchRawInfo in localBranchesRawInfo: for localBranchRawInfo in localBranchesRawInfo:
if (pattern.match(localBranchRawInfo)): if (pattern.match(localBranchRawInfo)):
localBranchName = _getBranchName(localBranchRawInfo) localBranchName = _get_branch_name(localBranchRawInfo)
nbWarnings += 1 nbWarnings += 1
pushableBranches.append(localBranchName) pushableBranches.append(localBranchName)
print yellow('Local branch "' + localBranchName + '" is ahead of remote branch.'); print yellow('Local branch "' + localBranchName + '" is ahead of remote branch.');
...@@ -118,31 +126,36 @@ def _checkLocalBranchesStatusVsRemote(localBranchesRawInfo, remoteName): ...@@ -118,31 +126,36 @@ def _checkLocalBranchesStatusVsRemote(localBranchesRawInfo, remoteName):
if (confirm(red('There are many local branches which are ahead of remote branch. Do you want to sync theses?'), default=False)): if (confirm(red('There are many local branches which are ahead of remote branch. Do you want to sync theses?'), default=False)):
for branchName in pushableBranches: for branchName in pushableBranches:
local('git push ' + remoteName + ' ' + branchName) local('git push ' + remoteName + ' ' + branchName)
# Do not alert with diff as local branches are now pushed # Do not alert with diff as local branches are now pushed
nbWarnings = 0 nbWarnings = 0
# TO DO : PUSHER LA BRANCHE SUR LE REPO # TODO
# PUSHER LA BRANCHE SUR LE REPO
return nbWarnings return nbWarnings
def _getLocalBranchesInformation():
def _get_local_branches_information():
return local('git branch --list -vv', capture=True).splitlines() return local('git branch --list -vv', capture=True).splitlines()
def _getBranchName(branchRawData):
def _get_branch_name(branchRawData):
branchName = branchRawData.replace('*', '').strip() branchName = branchRawData.replace('*', '').strip()
if (_isBranchDetached(branchName)): if (_is_branch_detached(branchName)):
return None return None
else: else:
return branchName.split()[0] return branchName.split()[0]
def _isBranchDetached(branchName):
def _is_branch_detached(branchName):
pattern = re.compile('\(.*\)') pattern = re.compile('\(.*\)')
return pattern.match(branchName) return pattern.match(branchName)