Commit 03eddeb6 authored by Victor Nikulshin's avatar Victor Nikulshin

Merge branch 'feature/coding-style' into '2.x'

Reformat code to match Python coding standards



See merge request !17
parents 4821cbb4 dd737731
Pipeline #1327 failed with stages
in 9 seconds
from fabric.api import task, env, execute
from fabric.colors import red
from fabric.contrib.console import confirm
import behat
import deploy
import docker
from deploy import *
import drush
import behat
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
def init():
"""
Complete local installation process, used generally when building the docker image for install and configure Drupal.
"""
execute(docker.image_create)
execute(docker.container_start)
execute(drush.make, 'install')
execute(drush.site_install, host='root@{}'.format(env.container_ip))
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
def install():
"""
Run the full installation process.
"""
execute(drush.make, 'install')
execute(drush.site_install)
execute(behat.init)
@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.make, 'update')
execute(drush.updatedb)
execute(behat.init)
execute(drush.archive_dump)
execute(drush.gen_doc)
@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)
execute(drush.gen_doc)
if not tags:
execute(behat.run)
else:
execute(behat.run, tags='{}'.format(tags))
@task
def deploy(environment):
"""Deploy code and run database updates on a target Drupal environment.
def update():
"""
execute(provision, environment)
execute(push, environment, hosts=env.hosts)
execute(migrate, environment, hosts=env.hosts)
Update the full codebase and run the availabe database updates.
"""
execute(drush.make, 'update')
execute(drush.updatedb)
execute(behat.init)
from __future__ import unicode_literals
from fabric.api import task, roles, env
from fabric.colors import green
import helpers as h
@task
@roles('docker')
def init(rewrite=True):
......@@ -12,7 +14,6 @@ def init(rewrite=True):
:param role Default 'role' where to run the task
:param rewrite If the behat.yml file should be rewrited or not.
"""
role = 'docker'
workspace = env.docker_workspace
host = env.site_hostname
......@@ -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@%URL@http://{}@g" behat.yml'.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))
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')
def install():
"""
Install behat
"""
role = 'docker'
workspace = env.docker_workspace
......@@ -44,6 +45,7 @@ def install():
h.fab_run(role, 'curl -s https://getcomposer.org/installer | php')
h.fab_run(role, 'php composer.phar install')
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')
else:
print(green('Behat is already installed, no need for a new installation'))
......@@ -56,7 +58,6 @@ def run(tags='~@wip&&~@disabled&&~@test'):
Execute the complete Behat tests suite.
:param role Default 'role' where to run the task
"""
role = 'docker'
workspace = env.docker_workspace
......@@ -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
if not h.fab_exists(role, '/usr/local/bin/behat') or not h.fab_exists(role, '../tests/behat/bin/behat'):
install()
# 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)):
init()
with h.fab_cd(role, '{}/tests/behat'.format(workspace)):
h.fab_run(role, 'behat --format junit --format pretty --tags "{}" --colors'.format(tags))
from __future__ import unicode_literals
from fabric.api import task, roles, env
from fabric.colors import red, green
import helpers as h
@task
@roles('docker')
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.
"""
if h.fab_exists(role, 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))
......
......@@ -33,6 +33,7 @@ env.site_languages = 'fr'
# PatternLab
# Specify the PatternLab dir is you want the style guide to be generated
env.patternlab_dir = ''
......@@ -41,6 +42,7 @@ env.patternlab_dir = ''
env.db_dump = False
# Docker
env.docker_workspace = '/opt/sfl'
......@@ -49,6 +51,7 @@ env.bind_port = 8001
env.apache_user = 'www-data'
# Docker auto-added container IP
env.container_ip = '172.17.0.0'
......
......@@ -17,13 +17,15 @@
#
from __future__ import unicode_literals
import glob
import os
from fabric.api import task, env, local, run
from fabric.colors import green
from fabric.utils import abort
import helpers as h
import os
import glob
def _set_hosts(environment):
......@@ -51,7 +53,9 @@ def _aegir_platform_name(target, environment):
"""
if 'aegir_platform' not in target:
abort('Aegir needs a unique platform name to function properly. Check your aegir_platform key in your aliases.')
aegir_platform = target.get('aegir_platform')
return aegir_platform.format(name=env.project_name, env=environment, build=env.build_number)
......@@ -61,8 +65,10 @@ def _target_dir(environment):
:param environment
"""
target = env.aliases.get(environment)
if _is_aegir_deployment(target):
return target.get('root') + _aegir_platform_name(target, environment)
return target.get('root')
......@@ -98,7 +104,6 @@ def _clear_site_cache(target, environment):
Helper function to clear site cache.
:param environment
"""
run('drush --yes --root={} cache-clear all'.format(target.get('root')))
print(green('The cache have been cleared on the target environment {}.'.format(environment)))
......@@ -109,10 +114,13 @@ def _get_archive_from_dir(directory):
:param directory The directory used to untar the artefact.
"""
files = glob.glob1(directory, '*.tar.gz')
if len(files) == 0:
abort('No tarball found in {}'.format(directory))
if len(files) > 1:
abort('More than one tarball has been found in {}. Can not decide which one to deploy.'.format(directory))
return files[0]
......@@ -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=@{}'
.format(aegir_path, platform, platform, aegir_destsrv))
run('drush @hostmaster hosting-import platform_{}'.format(platform))
run('drush @hostmaster hosting-dispatch')
......@@ -156,6 +165,15 @@ def _aegir_remove_platform_without_sites(target, 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
def provision(environment, role='local'):
"""
......@@ -169,10 +187,10 @@ def provision(environment, role='local'):
artefact = _get_archive_from_dir(env.builddir)
with h.fab_cd(role, '{}/src'.format(env.workspace)):
# Clear the currently installed platform
if h.fab_exists(role, env.site_root):
h.fab_run(role, 'rm -rf {}'.format(env.site_root))
# Extract the platform to deploy
h.fab_run(role, 'tar -xzf {}/{}'.format(env.builddir, artefact))
......@@ -186,12 +204,11 @@ def provision(environment, role='local'):
print(green('The platform {} is now ready to be deployed to the target environment {}.'.format(artefact,
environment)))
@task
def push(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_directory = _target_dir(environment)
......@@ -217,6 +234,7 @@ def migrate(environment):
if _is_aegir_deployment(target):
# Deploy to Aegir server.
platform = _aegir_platform_name(target, environment)
if env.get('migrate', "false") == "true":
_aegir_migrate_sites(target, environment, platform)
......
from __future__ import unicode_literals
from fabric.api import task, roles, env, local, run
from fabric.colors import red, green
import helpers as h
###########################################################
# Helper functions to manage docker images and containers #
###########################################################
def docker_ps(running_only=False):
args = '' if running_only else '-a'
result = local('docker ps %s' % args, capture=True)
......@@ -22,9 +25,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)
if not mounts:
mounts = []
if containername and containername in docker_ps(running_only=True):
print green("%s already running" % containername)
return False
if containername and containername in docker_ps(running_only=False):
if restart:
print green("%s already exists and is stopped. Restarting!" % containername)
......@@ -34,16 +39,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 "Run 'docker rm %s' to remove that container" % containername
return False
for from_path, to_path, canwrite in mounts:
abspath = from_path
opt = ' -v %s:%s' % (abspath, to_path)
if not canwrite:
opt += ':ro'
opts += opt
if containername:
containername_opt = '--name %s' % containername
else:
containername_opt = ''
local('docker run %s %s %s %s' % (opts, containername_opt, imgname, cmd))
return True
......@@ -70,8 +79,10 @@ def docker_ensure_data_container(containername, volume_paths=None, base_image='b
volume_args = ' '.join('-v %s' % volpath for volpath in volume_paths)
else:
volume_args = ''
local('docker create %s --name %s %s' % (volume_args, containername, base_image))
return True
return False
......@@ -86,8 +97,10 @@ def docker_isrunning(containername):
def docker_images():
result = local('docker images', capture=True)
lines = result.stdout.splitlines()
# image name is supposed to be the first column
assert lines[0].strip().startswith('REPOSITORY')
return [line.strip().split(' ')[0] for line in lines]
......@@ -109,12 +122,10 @@ def connect(role='local'):
@task
@roles('local')
def image_create(role='local'):
"""
Create docker images
:param role Default 'role' where to run the task
"""
with h.fab_cd(role, env.workspace):
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)))
......@@ -137,18 +148,18 @@ def container_start(role='local'):
'{}_container'.format(env.project_name),
'-d -p {}:80'.format(env.bind_port),
mounts=[(env.workspace, env.docker_workspace, True)]):
# 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}}}}" '
'{}_container'.format(env.project_name), capture=True)
if env.get('always_use_pty', True):
h.fab_update_hosts(env.container_ip, env.site_hostname)
print(green('Docker container {}_container was build successful. '
'To visit the Website open a web browser in http://{} or '
'http://localhost:{}.'.format(env.project_name, env.site_hostname, env.bind_port)))
h.fab_update_container_ip(env.container_ip)
else:
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 '
......@@ -166,6 +177,7 @@ def container_stop(role='local'):
if '{}_container'.format(env.project_name) in docker_ps():
if env.get('always_use_pty', True):
h.fab_remove_from_hosts(env.site_hostname)
h.fab_run(role, 'docker stop {}_container'.format(env.project_name))
print(green('Docker container {}_container was successful stopped'.format(env.project_name)))
else:
......@@ -184,14 +196,14 @@ def container_remove(role='local'):
if env.get('always_use_pty', True):
h.fab_remove_from_hosts(env.site_hostname)
h.fab_run(role, 'docker rm -f {}_container'.format(env.project_name))
print(green('Docker container {}_container was successful removed'.format(env.project_name)))
else:
print(red('Docker container {}_container was already removed'.format(env.project_name)))
@task()
@task
@roles('local')
def image_remove(role='local'):
"""
......@@ -205,9 +217,11 @@ def image_remove(role='local'):
env.project_name)))
if '{}/drupal'.format(env.project_name) in docker_images():
h.fab_run(role, 'docker rmi -f {}/drupal'.format(env.project_name))
# Remove dangling docker images to free space.
if '<none>' in docker_images():
h.fab_run(role, 'docker images --filter="dangling=true" -q | xargs docker rmi -f')
print(green('Docker image {}/drupal was successful removed'.format(env.project_name)))
else:
print(red('Docker image {}/drupal was not found'.format(env.project_name)))
......@@ -219,10 +233,10 @@ def update_host():
"""
Update hostname resolution in the container.
"""
site_hostname = run("hostname")
run("sed '/{}/c\{} {} localhost.domainlocal' "
"/etc/hosts > /root/hosts.backup".format(env.container_ip, env.container_ip, site_hostname))
run("cat /root/hosts.backup > /etc/hosts")
h.fab_update_container_ip()
......@@ -17,17 +17,17 @@
#
from __future__ import unicode_literals
from datetime import datetime
from fabric.api import task, roles, env
from fabric.contrib.console import confirm
from fabric.colors import red, green
from fabric.contrib.console import confirm
from fabric.utils import abort
from datetime import datetime
import helpers as h
import core as c
import helpers as h
from git import isGitDirty
from git import is_git_dirty
@task(alias='make')
......@@ -36,9 +36,8 @@ def make(action='install'):
"""
Build the platform by running the Makefile specified in the local_vars.py configuration file.
"""
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. '
'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))
......@@ -54,12 +53,15 @@ def make(action='install'):
drush_opts += "--translations=" + env.site_languages + " "
elif confirm(red('Say [Y] to {} the site at {} with the specified translation(s): {}. If you say [n] '
'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):
drush_opts += " --working-copy --no-gitinfofile"
if not h.fab_exists('local', env.site_root):
h.fab_run('local', "mkdir {}".format(env.site_root))
with h.fab_cd('local', env.site_root):
h.fab_run('local', 'drush make {} {} -y'.format(drush_opts, env.makefile))
......@@ -70,17 +72,18 @@ def aliases():
"""
Copy conf/aliases.drushrc.php in the site environment.
"""
role = 'docker'
drush_aliases = env.site_drush_aliases
workspace = env.docker_workspace
if not h.fab_exists(role, drush_aliases):
h.fab_run(role, 'mkdir -p {}'.format(drush_aliases))
with h.fab_cd(role, drush_aliases):
# Create 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, 'cp {}/conf/aliases.drushrc.php .'.format(workspace))
print(green('Drush aliases have been copied to {} directory.'.format(drush_aliases)))
......@@ -92,9 +95,7 @@ def updatedb():
"""
Run the available database updates. Similar to drush updatedb.
"""
role = 'docker'
with h.fab_cd(role, env.docker_site_root):
h.fab_run(role, 'drush updatedb -y')
h.hook_execute(env.hook_post_update, role)
......@@ -106,7 +107,6 @@ def site_install():
"""
Run the site installation procedure.
"""
role = 'docker'
site_root = env.docker_site_root
apache = env.apache_user
......@@ -153,18 +153,15 @@ def archive_dump(role='docker'):
Archive the platform for release or deployment.
:param role Default 'role' where to run the task
"""
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'))
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)))
h.fab_run(
role,
'drush archive-dump --destination={}/build/{} --tags="sflinux {}" --generatorversion="2.x" '
'--generator="Drupalizer::fab drush.archive_dump" --tar-options="--exclude=.git"'
''.format(env.docker_workspace, platform, env.project_name)
)
h.fab_run(role,
'drush archive-dump --destination={}/build/{} --tags="sflinux {}" --generatorversion="2.x" '
'--generator="Drupalizer::fab drush.archive_dump" --tar-options="--exclude=.git"'
''.format(env.docker_workspace, platform, env.project_name))
@task
......@@ -174,13 +171,14 @@ def gen_doc(role='docker'):
Generate README file
:param role Default 'role' where to run the task
"""
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'.
format(env.docker_workspace, env.docker_workspace))
print(green('README.html generated in {}'.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'.
format(env.docker_workspace, env.docker_workspace))
print(green('CHANGELOG.html generated in {}'.format(env.docker_workspace)))
......@@ -2,6 +2,7 @@ from importlib import import_module
from fabric.utils import abort
def e(name):
"""
Set your environment before running other commands
......
import re
import time
from os import path
from fabric.api import task, env, execute
from fabric.api import task, env, local
from fabric.colors import red, green, yellow
from fabric.api import task, env, execute
from fabric.contrib.console import confirm
from .environments import e
import helpers as h
import time
import re
from .environments import e
@task(alias='is_dirty')
def check_status():
"""
Check workspace's git repositories status.
"""
if (isGitDirty()):
if (is_git_dirty()):
print red('Your workspace is not clean.')
else:
print green('Your workspace is clean.')
def isGitDirty():
def is_git_dirty():
repos = local('find ' + path.normpath(env.workspace) + ' -name ".git"', capture=True).splitlines()
nbWarnings = 0
for repo in repos:
repoLocalPath = path.normpath(path.join(repo, '..'))
nbWarnings += _checkRepo(repoLocalPath)
nbWarnings += _check_repo(repoLocalPath)
return (nbWarnings > 0)
......@@ -39,7 +42,7 @@ def isGitDirty():
# - attention aux conflits, faire un pull d'abord et valider la fusion automatique
def _checkRepo(repoLocalPath):
def _check_repo(repoLocalPath):
nbWarnings = 0
with h.fab_cd('local', repoLocalPath):
print green('---')
......@@ -47,21 +50,21 @@ def _checkRepo(repoLocalPath):
remoteName = local('git remote', capture=True)
filesStatusRawInfo = _getFilesStatusInformation()
filesStatusRawInfo = _get_files_status_information()
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 + '"...');
nbWarnings += _checkLocalBranchesExistOnRemote(localBranchesRawInfo, remoteName)
nbWarnings += _check_local_branches_exist_on_remote(localBranchesRawInfo, remoteName)
print green('Verify branches status against remote...');
nbWarnings += _checkLocalBranchesStatusVsRemote(localBranchesRawInfo, remoteName)
nbWarnings += _check_local_branches_status_vs_remote(localBranchesRawInfo, remoteName)
return nbWarnings
def _checkFilesStatusVsHeadCommit(filesStatusRawInfo):
def _check_files_status_vs_head_commit(filesStatusRawInfo):
nbWarnings = 0
addableFiles = []
if (len(filesStatusRawInfo) > 0):
......@@ -70,8 +73,10 @@ def _checkFilesStatusVsHeadCommit(filesStatusRawInfo):
# Break loop if filename is "fabfile"
if fileStatusData[1] == 'fabfile':
break
nbWarnings += 1
addableFiles.append(fileStatusData[1])
print yellow('File "' + fileStatusData[1] + '" ' + {
'M': 'has un-commited modifications.',
'D': 'has been deleted.',
......@@ -80,12 +85,13 @@ def _checkFilesStatusVsHeadCommit(filesStatusRawInfo):
return nbWarnings
def _checkLocalBranchesExistOnRemote(localBranchesRawInfo, remoteName):
def _check_local_branches_exist_on_remote(localBranchesRawInfo, remoteName):
nbWarnings = 0
pushableBranches = []
for localBranchRawInfo in localBranchesRawInfo:
localBranchName = _getBranchName(localBranchRawInfo)
if ((localBranchName is not None) and (not _remoteBranchExists(localBranchName))):
localBranchName = _get_branch_name(localBranchRawInfo)
if ((localBranchName is not None) and (not _remote_branch_exists(localBranchName))):
nbWarnings += 1
pushableBranches.append(localBranchName)
print yellow('Local branch "' + localBranchName + '" is not present on "' + remoteName + '" remote.')
......@@ -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)):
for branchName in pushableBranches:
local('git push --set-upstream ' + remoteName + ' ' + branchName)
# Do not alert with diff as local branches are now pushed
nbWarnings = 0
return nbWarnings
def _checkLocalBranchesStatusVsRemote(localBranchesRawInfo, remoteName):
def _check_local_branches_status_vs_remote(localBranchesRawInfo, remoteName):
nbWarnings = 0
pushableBranches = []
# on gere un git FR ou EN, a voir ce qu'on peut faire
......@@ -108,7 +116,7 @@ def _checkLocalBranchesStatusVsRemote(localBranchesRawInfo, remoteName):
pattern = re.compile('.*\[.* (ahead|en avance de) .*\].*')
for localBranchRawInfo in localBranchesRawInfo:
if (pattern.match(localBranchRawInfo)):
localBranchName = _getBranchName(localBranchRawInfo)
localBranchName = _get_branch_name(localBranchRawInfo)
nbWarnings += 1
pushableBranches.append(localBranchName)
print yellow('Local branch "' + localBranchName + '" is ahead of remote branch.');
......@@ -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)):
for branchName in pushableBranches:
local('git push ' + remoteName + ' ' + branchName)
# Do not alert with diff as local branches are now pushed
nbWarnings = 0
# TO DO : PUSHER LA BRANCHE SUR LE REPO