ansible: apply roles.py fixes

Signed-off-by: Jakub Sokołowski <jakub@status.im>
This commit is contained in:
Jakub Sokołowski 2024-07-05 11:44:09 +02:00
parent d677afcd40
commit c03cf11c39
No known key found for this signature in database
GPG Key ID: FE65CD384D5BF7B4
1 changed files with 29 additions and 13 deletions

View File

@ -6,7 +6,8 @@ import argparse
import subprocess import subprocess
import functools import functools
from enum import Enum from enum import Enum
from os import path, getenv, symlink, readlink from pathlib import Path
from os import environ, path, getenv, symlink, readlink, makedirs
from packaging.version import parse as version_parse from packaging.version import parse as version_parse
from concurrent import futures from concurrent import futures
@ -66,9 +67,9 @@ class State(Enum):
CLONE_FAILURE = 7 CLONE_FAILURE = 7
MISSING = 8 MISSING = 8
CLONED = 9 CLONED = 9
UPDATED = 10 SKIPPED = 10
VALID = 11 VALID = 11
SKIPPED = 12 UPDATED = 12
def __str__(self): def __str__(self):
match self: match self:
@ -144,11 +145,16 @@ class Role:
def _git(self, *args, cwd=None): def _git(self, *args, cwd=None):
cmd = ['git'] + list(args) cmd = ['git'] + list(args)
env = dict(
environ,
GIT_SSH_COMMAND='ssh -o "StrictHostKeyChecking=accept-new"'
)
LOG.debug('[%-27s]: COMMAND: %s', self.name, ' '.join(cmd)) LOG.debug('[%-27s]: COMMAND: %s', self.name, ' '.join(cmd))
rval = subprocess.run( rval = subprocess.run(
cmd, cmd,
capture_output=True, capture_output=True,
cwd=cwd or self.path cwd=cwd or self.path,
env=env,
) )
LOG.debug('[%-27s]: RETURN: %d', self.name, rval.returncode) LOG.debug('[%-27s]: RETURN: %d', self.name, rval.returncode)
if rval.stdout: if rval.stdout:
@ -162,9 +168,9 @@ class Role:
try: try:
self._git(*args, cwd=cwd) self._git(*args, cwd=cwd)
except: except:
return True
else:
return False return False
else:
return True
@property @property
def repo_parent_dir(self): def repo_parent_dir(self):
@ -180,19 +186,23 @@ class Role:
return '........' return '........'
return self._git('rev-parse', 'HEAD') return self._git('rev-parse', 'HEAD')
@State.update(failure=State.DIRTY)
def has_upstream(self):
return self._git_fail_is_false('rev-parse', '--symbolic-full-name', '@{u}')
@State.update(success=State.DIRTY) @State.update(success=State.DIRTY)
def is_dirty(self): def is_dirty(self):
return self._git_fail_is_false('diff-files', '--quiet') return not self._git_fail_is_false('diff-files', '--quiet')
@State.update(success=State.DETACHED) @State.update(success=State.DETACHED)
def is_detached(self): def is_detached(self):
return self._git_fail_is_false('symbolic-ref', 'HEAD') return not self._git_fail_is_false('symbolic-ref', 'HEAD')
@State.update(success=State.NEWER_VERSION) @State.update(success=State.NEWER_VERSION)
def is_ancestor(self): def is_ancestor(self):
if self.required is None or self.required == self.current_commit: if self.required is None or self.required == self.current_commit:
return False return False
return not self._git_fail_is_false( return self._git_fail_is_false(
'merge-base', self.required, '--is-ancestor', self.current_commit 'merge-base', self.required, '--is-ancestor', self.current_commit
) )
@ -212,18 +222,20 @@ class Role:
def valid_version(self): def valid_version(self):
return self.required == self.current_commit return self.required == self.current_commit
@State.update(success=State.VALID, failure=State.WRONG_VERSION) @State.update(success=State.UPDATED, failure=State.WRONG_VERSION)
def pull(self): def pull(self):
self._git('remote', 'update') self._git('remote', 'update')
status = self._git('status', '--untracked-files=no') status = self._git('status', '--untracked-files=no')
if 'branch is up to date' in status: if 'branch is up to date' in status:
return True return self.version
elif 'branch is behind' not in status: elif 'branch is behind' not in status:
return None return None
rval = self._git('pull') rval = self._git('pull')
return self.valid_version()
self.version = self.current_commit
return self.current_commit
@State.update(success=State.CLONED, failure=State.CLONE_FAILURE) @State.update(success=State.CLONED, failure=State.CLONE_FAILURE)
def clone(self): def clone(self):
@ -274,7 +286,7 @@ def handle_role(role, check=False, update=False, install=False):
# Update config version or pull new changes. # Update config version or pull new changes.
if update: if update:
role.version = role.current_commit role.version = role.current_commit
elif install: elif install and role.has_upstream():
# If version is not specified we just want the newest. # If version is not specified we just want the newest.
role.pull() role.pull()
return role return role
@ -291,6 +303,9 @@ def roles_to_yaml(old_reqs, processed_roles):
def commit_or_any(commit): def commit_or_any(commit):
return '*' if commit is None else commit[:8] return '*' if commit is None else commit[:8]
def parent_path(str_path):
return Path(*Path(str_path).parts[:-1])
# Symlink only if folder or link doesn't exist. # Symlink only if folder or link doesn't exist.
def symlink_roles_dir(roles_symlink): def symlink_roles_dir(roles_symlink):
if path.islink(ROLES_PATH): if path.islink(ROLES_PATH):
@ -304,6 +319,7 @@ def symlink_roles_dir(roles_symlink):
LOG.error('Roles path is a directory, cannot symlink!') LOG.error('Roles path is a directory, cannot symlink!')
exit(1) exit(1)
makedirs(parent_path(ROLES_PATH))
symlink(roles_symlink, ROLES_PATH) symlink(roles_symlink, ROLES_PATH)
def parse_args(): def parse_args():