Skip to content

Commit

Permalink
feat(lint): support ruff C4 check
Browse files Browse the repository at this point in the history
  • Loading branch information
haidarCheaito committed Jan 2, 2024
1 parent e47f1ca commit c75f087
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 27 deletions.
76 changes: 59 additions & 17 deletions action.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ class BeanstalkEnvironment:
def get_health(self) -> dict:
return boto3.client("elasticbeanstalk").describe_environment_health(
EnvironmentName=self.name,
AttributeNames=["HealthStatus", "InstancesHealth", "Causes", "Color", "Status"],
AttributeNames=[
"HealthStatus",
"InstancesHealth",
"Causes",
"Color",
"Status",
],
)

def get_events(self, last_event_time: datetime) -> Sequence[dict]:
Expand All @@ -72,7 +78,9 @@ def wait_for_update_is_ready_and_get_health(
events = self.get_events(last_event_time)
health = self.get_health()

logging.info(f"Step {step + 1} of {polling_max_steps}. Status is {health['Status']}")
logging.info(
f"Step {step + 1} of {polling_max_steps}. Status is {health['Status']}",
)

# Log all events in order they occur beginning at the last event time
for event in events:
Expand Down Expand Up @@ -108,20 +116,34 @@ def create_zip() -> bytes:
with ZipFile(output_data, "w", compression=ZIP_DEFLATED) as archive:
archive.writestr(
"docker-compose.yml",
docker_compose_path.read_text().replace("${IMAGE_TAG}", version_label),
docker_compose_path.read_text().replace(
"${IMAGE_TAG}", version_label,
),
)
if platform_hooks_path is not None:
for file in filter(lambda path: path.is_file(), platform_hooks_path.glob("**/*")):
archive.write(file, arcname=file.relative_to(platform_hooks_path))
for file in filter(
lambda path: path.is_file(), platform_hooks_path.glob("**/*"),
):
archive.write(
file, arcname=file.relative_to(platform_hooks_path),
)

logging.info("Deployment archive created")
output_data.seek(0)
return output_data.getvalue()

def upload_zip(content: bytes) -> DeploymentArchive:
boto3.client("s3").put_object(Bucket=bucket_name, Body=content, Key=bucket_key)
logging.info(f"Deployment archive uploaded to s3://{bucket_name}/{bucket_key}")
return DeploymentArchive(version_label=version_label, bucket_name=bucket_name, bucket_key=bucket_key)
boto3.client("s3").put_object(
Bucket=bucket_name, Body=content, Key=bucket_key,
)
logging.info(
f"Deployment archive uploaded to s3://{bucket_name}/{bucket_key}",
)
return DeploymentArchive(
version_label=version_label,
bucket_name=bucket_name,
bucket_key=bucket_key,
)

return upload_zip(create_zip())

Expand All @@ -133,7 +155,9 @@ class ApplicationVersion:
status: str

@classmethod
def get(cls, application: BeanstalkApplication, version_label: str) -> Optional[Self]:
def get(
cls, application: BeanstalkApplication, version_label: str,
) -> Optional[Self]:
versions = boto3.client("elasticbeanstalk").describe_application_versions(
ApplicationName=application.name,
VersionLabels=[version_label],
Expand Down Expand Up @@ -178,16 +202,24 @@ def wait_until_created():
step = 0
while step < polling_max_steps:
application_version = cls.get(application, version_label)
status = "UNAVAILABLE" if application_version is None else application_version.status
status = (
"UNAVAILABLE"
if application_version is None
else application_version.status
)

logging.info(f"Step {step + 1} of {polling_max_steps}. Status is {status}")
logging.info(
f"Step {step + 1} of {polling_max_steps}. Status is {status}",
)
if status == "PROCESSED":
return application_version

time.sleep(polling_interval.total_seconds())
step += 1

raise TimeoutError("Application Version creation not finished until timeout")
raise TimeoutError(
"Application Version creation not finished until timeout",
)

return wait_until_created()

Expand All @@ -209,7 +241,9 @@ def deploy_to_environment(
assert environment.application == self.application

if self.is_active_in_environment(environment):
logging.info(f"{self.version_label} already active in {environment.name}, skip update!")
logging.info(
f"{self.version_label} already active in {environment.name}, skip update!",
)
return

boto3.client("elasticbeanstalk").update_environment(
Expand Down Expand Up @@ -262,7 +296,9 @@ def get_or_create_beanstalk_application_version(
def check_aws_credentials():
aws_credential_variables = ("AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY")
if not all(variable in os.environ for variable in aws_credential_variables):
raise ValueError(f"AWS credentials not configured ({', '.join(aws_credential_variables)})")
raise ValueError(
f"AWS credentials not configured ({', '.join(aws_credential_variables)})",
)


def get_region() -> str:
Expand All @@ -271,7 +307,9 @@ def get_region() -> str:
if region := os.environ.get(region_var):
return region

raise ValueError(f"AWS region not configured, set one of ({', '.join(region_variables)})")
raise ValueError(
f"AWS region not configured, set one of ({', '.join(region_variables)})",
)


def main():
Expand All @@ -281,15 +319,19 @@ def main():
description=os.environ["VERSION_DESCRIPTION"],
docker_compose_path=Path(os.environ["DOCKER_COMPOSE_PATH"]),
environment_name=os.environ["ENVIRONMENT_NAME"],
platform_hooks_path=Path(os.environ["PLATFORM_HOOKS_PATH"]) if os.environ["PLATFORM_HOOKS_PATH"] else None,
platform_hooks_path=Path(os.environ["PLATFORM_HOOKS_PATH"])
if os.environ["PLATFORM_HOOKS_PATH"]
else None,
region=get_region(),
version_label=os.environ["VERSION_LABEL"],
)

application = BeanstalkApplication(config.application_name)
environment = BeanstalkEnvironment(application, config.environment_name)

application_version = get_or_create_beanstalk_application_version(application, config)
application_version = get_or_create_beanstalk_application_version(
application, config,
)

application_version.deploy_to_environment(environment)

Expand Down
42 changes: 32 additions & 10 deletions test_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@
version_label="abc123456",
)
MOCK_APPLICATION = action.BeanstalkApplication(MOCK_CONFIG.application_name)
MOCK_ENVIRONMENT = action.BeanstalkEnvironment(MOCK_APPLICATION, MOCK_CONFIG.environment_name)
MOCK_APPLICATION_VERSION = action.ApplicationVersion(MOCK_APPLICATION, "version-0", "PROCESSED")
MOCK_ENVIRONMENT = action.BeanstalkEnvironment(
MOCK_APPLICATION, MOCK_CONFIG.environment_name,
)
MOCK_APPLICATION_VERSION = action.ApplicationVersion(
MOCK_APPLICATION, "version-0", "PROCESSED",
)
MOCK_TIME = datetime.now(tz=UTC)


class TestUtils(TestCase):
def test_check_aws_credentials(self):
with patch.dict(os.environ, {"AWS_ACCESS_KEY_ID": "fake", "AWS_SECRET_ACCESS_KEY": "fake"}):
with patch.dict(
os.environ, {"AWS_ACCESS_KEY_ID": "fake", "AWS_SECRET_ACCESS_KEY": "fake"},
):
action.check_aws_credentials()

with self.assertRaises(ValueError):
Expand All @@ -42,8 +48,12 @@ def test_get_region(self):


class TestApplicationVersion(TestCase):
def _get_or_create_application_version(self, polling_results: Sequence[Optional[action.ApplicationVersion]]):
with NamedTemporaryFile() as docker_compose_file, patch.object(action, "boto3"), patch.object(
def _get_or_create_application_version(
self, polling_results: Sequence[Optional[action.ApplicationVersion]],
):
with NamedTemporaryFile() as docker_compose_file, patch.object(
action, "boto3",
), patch.object(
action.ApplicationVersion,
"get",
side_effect=polling_results,
Expand All @@ -57,12 +67,16 @@ def _get_or_create_application_version(self, polling_results: Sequence[Optional[
polling_interval=timedelta(0),
polling_max_steps=len(polling_results) - 1,
)
self.assertEqual(mock_get_application_version.call_count, len(polling_results))
self.assertEqual(
mock_get_application_version.call_count, len(polling_results),
)
return result

def test_version_exists(self):
with self.assertLogs() as captured:
result = self._get_or_create_application_version((MOCK_APPLICATION_VERSION,))
result = self._get_or_create_application_version(
(MOCK_APPLICATION_VERSION,),
)
self.assertEqual(result, MOCK_APPLICATION_VERSION)
self.assertEqual(
captured.records[0].getMessage(),
Expand All @@ -86,7 +100,11 @@ def test_timeout_error(self):


class TestDeployment(TestCase):
def _deploy(self, get_health_return_values: Sequence[dict], is_active_in_environment: Sequence[bool]):
def _deploy(
self,
get_health_return_values: Sequence[dict],
is_active_in_environment: Sequence[bool],
):
with patch.object(
action.BeanstalkEnvironment,
"get_health",
Expand Down Expand Up @@ -114,7 +132,9 @@ def _deploy(self, get_health_return_values: Sequence[dict], is_active_in_environ
self.assertEqual(mock_get_health.call_count, iterations)
self.assertEqual(mock_get_events.call_count, iterations)
mock_is_active_in_environment.assert_called_with(MOCK_ENVIRONMENT)
self.assertEqual(mock_is_active_in_environment.call_count, len(is_active_in_environment))
self.assertEqual(
mock_is_active_in_environment.call_count, len(is_active_in_environment),
)

def test_successful_deployment(self):
self._deploy(
Expand All @@ -127,7 +147,9 @@ def test_successful_deployment(self):

def test_environment_timeout_error(self, *_):
with self.assertRaises(TimeoutError):
self._deploy(({"Status": "InProgress", "Color": "Grey"},) * 5, (False, True))
self._deploy(
({"Status": "InProgress", "Color": "Grey"},) * 5, (False, True),
)

def test_health_failed(self):
with self.assertRaises(RuntimeError):
Expand Down

0 comments on commit c75f087

Please sign in to comment.