Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .config.sample.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
token: token
version: version
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -275,3 +275,4 @@ pyrightconfig.json
.ionide

*pruebas.ipynb
.config.yaml
7 changes: 7 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import os
from src.app_updater import AppUpdater

if __name__ == '__main__':
if not os.getenv("CORE_BE_TOKEN"):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lo tomaria del .config.yaml agregar variables de entorno en windows es mas dificil agregarlo

print("No se ha configurado el token de acceso a core-be")
AppUpdater().update_source_code_automaticaly()
652 changes: 651 additions & 1 deletion poetry.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ gitpython = "^3.1.32"
[tool.poetry.group.dev.dependencies]
coverage = "^7.2.7"
flake8 = "^6.1.0"
ipykernel = "^6.25.1"

[build-system]
requires = ["poetry-core"]
Expand Down
71 changes: 52 additions & 19 deletions src/app_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import subprocess
import traceback
import yaml
from src.core_service import CoreService

from packaging import version
from pwinput import pwinput
Expand All @@ -12,14 +13,15 @@
from src.email_sender import EmailSender
from .github_repository import GithubRepository


class AppUpdater:
use_core_be = True
max_input_retries = 3
organization_name = "core-webapp"
repository_name = "core_legacy"
user_input_true = 'y'
license_path = Path() / repository_name / 'state' / 'utils' / 'license.yaml'
requirements_path = Path() / repository_name / 'requirements.txt'
config_file_path = Path() / '.config.yaml'

# TODO where should we add the developers? harcoded here or in a config file?
developers: tuple[str]
Expand All @@ -30,6 +32,9 @@ class AppUpdater:

changes_made = []

def __init__(self, core_service_repo_klass: type[CoreService]=CoreService):
self.core_service_repo = core_service_repo_klass()

def install_source_code(self):

# TODO: get token from user and if it is valid continue
Expand All @@ -49,34 +54,62 @@ def install_source_code(self):
# TODO: send mail with a resume of the new changes
pass

def update_source_code(self):

token = self._get_api_token()
github_repository = GithubRepository(token)

if self._there_is_a_newer_version(github_repository):
self._update_to_new_version_if_operator_wants(github_repository)
def update_source_code_automaticaly(self):
if self.use_core_be:
version_control_info = self.core_service_repo.get_version_control_info()
token = version_control_info.get('token')
version_tag = version_control_info.get('version')
else:
token = self._get_api_token('automatic')
version_tag = self._get_version_tag_to_update()

github_repository = GithubRepository(
token,
self.organization_name,
self.repository_name,
)
self._update_to_new_version(github_repository, version_tag)

self._install_dependencies_from_requirements()
# self._install_dependencies_from_requirements()

self.update_the_license_if_operator_wants()
# self._run_database_migration()
# self._send_email_with_resume_of_changes()

# TODO: ask the operator if wants to update the database, include an migration tool like alembic for this
@classmethod
def _get_api_token(cls, mode: str = 'manual') -> str:
if mode == 'automatic':
return cls._get_api_token_automaticaly()

self._send_email_with_resume_of_changes()
return cls._get_api_token_manualy()

@classmethod
def _get_api_token_from_user(cls):
return pwinput('Enter your API TOKEN: ')
def _get_api_token_automaticaly(cls) -> str:
with open(cls.config_file_path, 'rb') as file:
raw_yaml_config = file.read()
config = yaml.safe_load(raw_yaml_config)
token = config.get('token')
return token

@classmethod
def _get_api_token(cls):
def _get_api_token_manualy(cls):
for _ in range(cls.max_input_retries):
api_token = cls._get_api_token_from_user()
if GithubRepository._is_token_valid(api_token):
return api_token
raise Exception('Max retries exceeded')

@classmethod
def _get_api_token_from_user(cls):
return pwinput('Enter your API TOKEN: ')

@classmethod
def _get_version_tag_to_update(cls) -> str:
with open(cls.config_file_path, 'rb') as file:
raw_yaml_config = file.read()
config = yaml.safe_load(raw_yaml_config)
token = config.get('version')
return token

def _there_is_a_newer_version(self, github_repository: GithubRepository) -> bool:
# FIXME : it's not a good idea to set values ina method that does another thing
# but for now is the easy and fast way to do it, I will refactor later
Expand Down Expand Up @@ -121,11 +154,11 @@ def _operator_wants(self, user_messages: UserMessages) -> bool:
answer = input(user_messages.input).lower()
return answer == self.user_input_true

def _update_to_new_version(self, github_repository: GithubRepository):
commit_of_last_release = github_repository.commit_of_last_release
github_repository.change_source_code_version(commit_of_last_release)
def _update_to_new_version(self, github_repository: GithubRepository, version_tag: str = 'qa') -> None:
version_commit = github_repository.get_commit_sha_of_version_tag(version_tag)
github_repository.change_source_code_version(version_commit)
self._log_change(
f"Se actualizo a la version {github_repository.last_release} - commit {commit_of_last_release}\n\n"
f"Se actualizo a la version {version_tag} - commit {version_commit}\n\n"
)

def _log_change(self, change: str) -> None:
Expand Down
24 changes: 24 additions & 0 deletions src/core_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import os
import requests


class CoreService:
BASE_URL = os.getenv("CORE_BE_URL")

def __init__(self, token=None):
self.token = token if token else os.getenv("CORE_BE_TOKEN")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


def get_version_control_info(self):
url = f"{self.BASE_URL}api/company/version-control/me/"
try:
response = requests.get(
url, headers={"Authorization": f"Token {self.token}"}
)
except Exception as e:
raise Exception(f"There was an error calling to core-be - {e}")

if response.status_code == 200:
return response.json()
raise Exception(
f"There was an error getting the config - {response.status_code} - {response.reason()}"
)
6 changes: 5 additions & 1 deletion src/github_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,12 @@ def _get_last_release(self) -> str:
latest_release = self.repository.get_latest_release()
return latest_release.tag_name

def get_commit_sha_of_version_tag(self, version_tag: str) -> str:
commit = self.repository.get_git_ref(f"tags/{version_tag}")
return commit.object.sha

def _get_commit_sha_of_release(self, release: GitRelease.GitRelease) -> str:
release_commit = self.repository.get_git_ref(f"tags/{release.tag_name}")
release_commit = self.repository.get_git_ref(f"tags/{release}")
return release_commit.object.sha

def _clone_repository(self, repository_url: str, path_to_clone_the_app: str):
Expand Down
30 changes: 24 additions & 6 deletions test/test_app_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@
from src.github_repository import GithubRepository


@pytest.fixture
def mock_github_repository() -> GithubRepository:
with patch.object(GithubRepository, '__init__', return_value=None):
github_repository = GithubRepository(
'fake_api_token',
'fake_organization_name',
'fake_repository_name',
)
return github_repository


@pytest.mark.parametrize(
"user_input, expected", [
('1234567890', '1234567890'),
Expand Down Expand Up @@ -269,16 +280,23 @@ def test_operator_wants(
assert result == expected_result


def test_update_to_new_version():
@patch.object(GithubRepository, 'change_source_code_version')
@patch.object(GithubRepository, 'get_commit_sha_of_version_tag')
def test_update_to_new_version(
patched_get_commit_sha_of_version_tag: MagicMock,
patched_change_source_code_version: MagicMock,
mock_github_repository: GithubRepository,
):
# prepare
fake_commit_of_last_release = 'fake_commit_of_last_release'
mock_github_repository = Mock()
mock_github_repository.commit_of_last_release = fake_commit_of_last_release
fake_version_tag = 'fake_version_tag'
fake_version_commit = 'fake_version_commit'
patched_get_commit_sha_of_version_tag.return_value = fake_version_commit

app_updater = AppUpdater()

# test
app_updater._update_to_new_version(mock_github_repository)
app_updater._update_to_new_version(mock_github_repository, fake_version_tag)

# asserts
mock_github_repository.change_source_code_version.assert_called_once_with(fake_commit_of_last_release)
mock_github_repository.get_commit_sha_of_version_tag.assert_called_once_with(fake_version_tag)
mock_github_repository.change_source_code_version.assert_called_once_with(fake_version_commit)
5 changes: 2 additions & 3 deletions test/test_github_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,7 @@ def test_get_commit_sha_of_release():
# prepare
expected_commit_sha = "expected_commit_sha"

mock_release = Mock()
mock_release.tag_name = "some_tag_name"
mock_release = "mock_release"

mock_release_commit = Mock()
mock_release_commit.object.sha = expected_commit_sha
Expand All @@ -242,7 +241,7 @@ def test_get_commit_sha_of_release():
last_release = mock_github_repository._get_commit_sha_of_release(mock_release)

# asserts
mock_repository.get_git_ref.assert_called_once_with(f"tags/{mock_release.tag_name}")
mock_repository.get_git_ref.assert_called_once_with(f"tags/{mock_release}")
assert last_release == expected_commit_sha


Expand Down