From d86eaf9956fc479526db65e88927074b66bef7bb Mon Sep 17 00:00:00 2001 From: Oscar Levin Date: Sun, 6 Aug 2023 14:04:13 +0000 Subject: [PATCH 1/2] wire up deploy with refactor --- pretext/cli.py | 20 +++------- pretext/project/__init__.py | 79 +++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 14 deletions(-) diff --git a/pretext/cli.py b/pretext/cli.py index 4d2b15a9..5d1c0110 100644 --- a/pretext/cli.py +++ b/pretext/cli.py @@ -514,12 +514,11 @@ def generate( try: target = project.get_target(name=target_name) except AssertionError as e: - utils.show_target_hints(target_name, project, task="generating assets for") log.critical("Exiting without completing build.") log.debug(e, exc_info=True) return - + try: f'Generating assets in for the target "{target.name}".' target.generate_assets( @@ -673,32 +672,25 @@ def view( context_settings=CONTEXT_SETTINGS, ) @click.argument("target_name", metavar="target", required=False) -@click.option( - "-s", - "--site", - required=False, - default="site", - help="Relative path to a directory containing html for a landing page.", -) @click.option("-u", "--update_source", is_flag=True, required=False) -def deploy(target_name: str, site: str, update_source: bool) -> None: +def deploy(target_name: str, update_source: bool) -> None: """ Automatically deploys most recent build of [TARGET] to GitHub Pages, making it available to the general public. Requires that your project is under Git version control properly configured with GitHub and GitHub Pages. Deployed - files will live in `docs` subdirectory of project. + files will live in the gh-pages branch of your repository. """ if utils.no_project(task="deploy"): return project = Project.parse() target = project.get_target(name=target_name) - if target.format != Format.HTML: + if target.format not in [Format.HTML, Format.RUNESTONE]: log.critical("Target could not be found in project.ptx manifest.") # only list targets with html format. log.critical( - f"Possible html targets to deploy are: {project.target_names('html')}" + f"Possible html/Runestone targets to deploy are: {project.target_names(Format.HTML)}" ) log.critical("Exiting without completing task.") return - project.deploy(target_name, site, update_source) + project.deploy(target_name, update_source) diff --git a/pretext/project/__init__.py b/pretext/project/__init__.py index 9758d3d3..735be318 100644 --- a/pretext/project/__init__.py +++ b/pretext/project/__init__.py @@ -1,3 +1,4 @@ +import subprocess import typing as t from enum import Enum import hashlib @@ -998,6 +999,9 @@ def publication_abspath(self) -> Path: def output_dir_abspath(self) -> Path: return self.abspath() / self.output_dir + def site_abspath(self) -> Path: + return self.abspath() / self.site + def xsl_abspath(self) -> Path: return self.abspath() / self.xsl @@ -1024,3 +1028,78 @@ def get_executables(self) -> Executables: def init_core(self) -> None: core.set_executables(self._executables.dict()) + + def deploy_targets(self) -> t.List[Target]: + return [target for target in self.targets if target.site is not None] + + def deploy(self, target_name: str, update_source: bool) -> None: + # Before doing any work, we check that git is installed. + try: + subprocess.run(["git", "--version"], capture_output=True) + log.debug("Git is installed.") + except Exception as e: + log.error( + "Git must be installed to use this feature, but couldn't be found." + ) + log.debug(f"Error: {e}", exc_info=True) + return + # Determine what set of targets to deploy. If a target name is specified, deploy on that target. If there are `deploy-dir` specified in the project manifest, also deploy the contents of the `site` folder, if present. + if len(self.deploy_targets()) == 0: + target = self.get_target(target_name) + if target is None: + log.error(f"Target `{target_name}` not found.") + return + if target.format not in [ + Format.HTML, + Format.RUNESTONE, + ]: # redundant for CLI + log.error("Only HTML and Runestone format targets are supported.") + return + if not target.output_dir_abspath().exists(): + log.error( + f"No build for `{target.name}` was found in the directory `{target.output_dir_abspath()}`." + ) + log.error( + f"Try running `pretext view {target.name} -b` to build and preview your project first." + ) + return + log.info(f"Using latest build located in `{target.output_dir_abspath()}`.") + log.info("") + utils.publish_to_ghpages(target.output_dir_abspath(), update_source) + return + else: # we now deploy multiple targets and the site directory + if not self.site_abspath().exists: + log.error(f"Site directory `{self.site}` not found.") + log.info( + f"You have `deploy-dir` or `site` (v2) elements in your project.ptx file, which requires you to maintain at least a simple landing page in the folder `{self.site}`. Either create this folder or remove the `deploy-dir` elements from your project.ptx file.\n" + ) + return + with tempfile.TemporaryDirectory() as temp_dir: + shutil.copytree( + self.site.resolve(), + Path(temp_dir), + dirs_exist_ok=True, + ) + for target in self.deploy_targets(): + if not target.output_dir_abspath().exists(): + log.warning( + f"No build for `{target.name}` was found in the directory `{target.output_dir_abspath()}`. Try running `pretext build {target.name}` to build this component first." + ) + log.info("Skipping this target for now.") + else: + deploy_dir = target.site + assert isinstance(deploy_dir, str) + shutil.copytree( + target.output_dir_abspath(), + (Path(temp_dir) / deploy_dir).resolve(), + dirs_exist_ok=True, + ) + log.info(f"Deploying `{target.name}` to `{target.site}`.") + # Recopy the site's index.html (if it exists) to the root of the temp directory. This is a bit of a hack, but it's the simplest way to ensure that the site's landing page is deployed. + if (self.site_abspath() / "index.html").exists(): + shutil.copy( + self.site_abspath() / "index.html", + Path(temp_dir), + ) + utils.publish_to_ghpages(Path(temp_dir), update_source) + return From d528ede273a2c29d13f6e0a44ebc30871ac9da84 Mon Sep 17 00:00:00 2001 From: Oscar Levin Date: Sun, 6 Aug 2023 14:11:36 +0000 Subject: [PATCH 2/2] clean up --- pretext/cli.py | 21 --------------------- pretext/project/__init__.py | 2 +- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/pretext/cli.py b/pretext/cli.py index 5d1c0110..574d416e 100644 --- a/pretext/cli.py +++ b/pretext/cli.py @@ -77,27 +77,6 @@ def main(ctx: click.Context, targets: bool) -> None: `pretext build --help`. """ if (pp := utils.project_path()) is not None: - try: - ProjectRefactor.parse(pp) - log.info( - "------------------------------------\n Good news: \n Your project.ptx file is ready for\n the 2.0.0 release of PreTeXt-CLI.\n------------------------------------\n" - ) - except Exception as e: - log.warning( - "Your project.ptx or publication file may not be compatible with the " - + "upcoming 2.0.0 release of PreTeXt-CLI." - ) - log.warning( - "For more information or to help us fix a possible bug, please visit" - ) - log.warning(" https://groups.google.com/g/pretext-support/c/bwf51qOoT9c") - log.warning( - "and share the result of running `pretext support` on your machine with us." - ) - log.info("") - log.warning(f"Exception info: {e}") - log.info("") - log.warning("Continuing with current version...") if targets: for target in Project.parse(pp).target_names(): print(target) diff --git a/pretext/project/__init__.py b/pretext/project/__init__.py index 735be318..74613e32 100644 --- a/pretext/project/__init__.py +++ b/pretext/project/__init__.py @@ -1087,7 +1087,7 @@ def deploy(self, target_name: str, update_source: bool) -> None: ) log.info("Skipping this target for now.") else: - deploy_dir = target.site + deploy_dir = str(target.site) assert isinstance(deploy_dir, str) shutil.copytree( target.output_dir_abspath(),