From 6c1f536a863d0dec4fa9ee8049874dacf97d00c5 Mon Sep 17 00:00:00 2001 From: Yanks Yoon <37652070+yanksyoon@users.noreply.github.com> Date: Tue, 21 Mar 2023 10:00:46 +0800 Subject: [PATCH] fix: restart after assets compile (#47) * fix: restart after assets compile * test: add compiled asset test * fix: lint fixes * chore: match service name * chore: add pebble issue comment * chore: split comment(lint issue) --- src/charm.py | 18 +++++++++++------- tests/integration/test_charm.py | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/charm.py b/src/charm.py index 126eb8e6..8baa6ef8 100755 --- a/src/charm.py +++ b/src/charm.py @@ -18,7 +18,7 @@ from ops.framework import StoredState from ops.main import main from ops.model import ActiveStatus, BlockedStatus, MaintenanceStatus, WaitingStatus -from ops.pebble import ExecError, Plan +from ops.pebble import ExecError, ExecProcess, Plan logger = logging.getLogger(__name__) pgsql = ops.lib.use("pgsql", 1, "postgresql-charmers@lists.launchpad.net") @@ -301,7 +301,7 @@ def _create_layer_config(self) -> Dict[str, Any]: "summary": "Discourse layer", "description": "Discourse layer", "services": { - "discourse": { + SERVICE_NAME: { "override": "replace", "summary": "Discourse web application", "command": f"sh -c '{SCRIPT_PATH}/app_launch.sh'", @@ -372,21 +372,21 @@ def _set_up_discourse(self, event: HookEvent) -> None: try: if self.model.unit.is_leader(): self.model.unit.status = MaintenanceStatus("Executing migrations") - process = container.exec( + migration_process: ExecProcess = container.exec( [f"{DISCOURSE_PATH}/bin/bundle", "exec", "rake", "--trace", "db:migrate"], environment=env_settings, working_dir=DISCOURSE_PATH, user="discourse", ) - process.wait_output() + migration_process.wait_output() self.model.unit.status = MaintenanceStatus("Compiling assets") - process = container.exec( + precompile_process: ExecProcess = container.exec( [f"{DISCOURSE_PATH}/bin/bundle", "exec", "rake", "assets:precompile"], environment=env_settings, working_dir=DISCOURSE_PATH, user="discourse", ) - process.wait_output() + precompile_process.wait_output() except ExecError as cmd_err: logger.exception("Setting up discourse failed with code %d.", cmd_err.exit_code) raise @@ -446,7 +446,11 @@ def _reload_configuration(self) -> None: if self._is_config_valid() and container.can_connect(): layer_config = self._create_layer_config() container.add_layer(SERVICE_NAME, layer_config, combine=True) - container.pebble.replan_services() + # Currently, pebble replan will cause + # ChangeError("cannot start service while terminating".) + # Link to issue: https://github.com/canonical/pebble/issues/206 + container.stop(SERVICE_NAME) + container.start(SERVICE_NAME) self.ingress.update_config(self._make_ingress_config()) def _redis_relation_changed(self, _: HookEvent) -> None: diff --git a/tests/integration/test_charm.py b/tests/integration/test_charm.py index 182bd152..b8564e05 100644 --- a/tests/integration/test_charm.py +++ b/tests/integration/test_charm.py @@ -346,3 +346,21 @@ async def test_create_category( assert category["name"] == category_info["name"] assert category["color"] == category_info["color"] + + +@pytest.mark.asyncio +async def test_serve_compiled_assets( + discourse_address: str, +): + """ + arrange: Given discourse application + act: when accessing a page that does not exist + assert: a compiled asset should be served. + """ + res = requests.get(f"{discourse_address}/404", timeout=60) + not_found_page = str(res.content) + + asset_matches = re.search( + r"(onpopstate-handler).+.js", not_found_page + ) # a non-compiled asset will be named onpopstate-handler.js + assert asset_matches, "Compiled asset not found."