From 5aabea7c356ae189d8ca405283b296d4858aa4e7 Mon Sep 17 00:00:00 2001 From: Deniz Turgut Date: Sun, 30 Apr 2023 21:19:32 +0300 Subject: [PATCH 1/3] remove missing Nuja theme --- .gitmodules | 3 --- Nuja | 1 - 2 files changed, 4 deletions(-) delete mode 160000 Nuja diff --git a/.gitmodules b/.gitmodules index fcd145b5..4d63e79f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -143,9 +143,6 @@ [submodule "alchemy"] path = alchemy url = https://github.com/nairobilug/pelican-alchemy.git -[submodule "Nuja"] - path = Nuja - url = https://github.com/allenskd/Nuja.git [submodule "pjport"] path = pjport url = https://github.com/xm3ron/pjport.git diff --git a/Nuja b/Nuja deleted file mode 160000 index a58fd614..00000000 --- a/Nuja +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a58fd6149d83c1b262a75cac785b51e8e6fb0dd9 From 2c54ecc738ad13f804add85a5dbd43b2a0c36501 Mon Sep 17 00:00:00 2001 From: Deniz Turgut Date: Mon, 1 May 2023 01:08:23 +0300 Subject: [PATCH 2/3] add preview site build script and github actions workflow Co-authored-by: matt wilkie --- .github/workflows/build-preview-site.yml | 65 +++++++ .gitignore | 5 + build-theme-previews.py | 237 +++++++++++++++++++++++ 3 files changed, 307 insertions(+) create mode 100644 .github/workflows/build-preview-site.yml create mode 100644 build-theme-previews.py diff --git a/.github/workflows/build-preview-site.yml b/.github/workflows/build-preview-site.yml new file mode 100644 index 00000000..6dd2cc9c --- /dev/null +++ b/.github/workflows/build-preview-site.yml @@ -0,0 +1,65 @@ +name: Build pelican-themes preview site + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow one concurrent deployment +concurrency: + group: "pages" + cancel-in-progress: true + +on: + # Triggers the workflow on push or pull request events but only for the "main" branch + push: + branches: [ "master" ] + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - name: Checkout repo + uses: actions/checkout@v3 + with: + fetch-depth: 1 + submodules: recursive + - name: Checkout pelican + uses: actions/checkout@v3 + with: + repository: getpelican/pelican + path: _pelican + fetch-depth: 1 + - name: Setup python-3.10 + uses: actions/setup-python@v4 + with: + python-version: "3.10" + - name: Cache Playwright browsers + uses: actions/cache@v3 + with: + path: ~/.cache/ms-playwright/ + key: ${{ runner.os }}-browsers + - name: Install pelican and shot-scraper + run: pip install pelican[markdown] shot-scraper + - name: Setup shot-scraper + run: shot-scraper install + - name: Generate output + run: python build-theme-previews.py + + # Deploy to Github Pages + - name: Setup Pages + uses: actions/configure-pages@v2 + - name: Upload artifact + uses: actions/upload-pages-artifact@v1 + with: + path: '_output' + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v1 \ No newline at end of file diff --git a/.gitignore b/.gitignore index f791bb41..e79f6b5b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,8 @@ Thumbs.db *~ .swp .*.swp + +# Preview artifacts # +##################### +_pelican +_output \ No newline at end of file diff --git a/build-theme-previews.py b/build-theme-previews.py new file mode 100644 index 00000000..fa766f8a --- /dev/null +++ b/build-theme-previews.py @@ -0,0 +1,237 @@ +import argparse +import logging +import subprocess +import os + +from rich.logging import RichHandler +from rich.console import Console + + +FORMAT = "%(message)s" +logging.basicConfig( + level="NOTSET", + format=FORMAT, + datefmt="[%X]", + handlers=[RichHandler(show_path=False, console=Console(force_terminal=True))] +) +logger = logging.getLogger() + +HTML_HEADER = """\ + + + + + + +

pelican-themes Preview

+
    """ + +HTML_FOOTER = """\ +
+ + + +""" + + +def setup_folders(args): + theme_root = os.path.abspath(os.path.dirname(__file__)) + output_root = os.path.abspath(os.path.join(theme_root, args.output)) + samples_root = os.path.abspath(os.path.join(theme_root, args.samples)) + screenshot_root = os.path.abspath(os.path.join(output_root, "_screenshots")) + + # requires `getpelican/pelican` cloned in `_pelican` folder + if os.path.exists(samples_root): + os.makedirs(os.path.join(samples_root, "content", "images"), exist_ok=True) # silence warning + else: + raise RuntimeError( + f"Samples folder does not exist: {samples_root}. " + "You can use `samples` from pelican by cloning it to `_pelican` folder" + ) + # create output and screenshot folders + os.makedirs(output_root, exist_ok=True) + os.makedirs(screenshot_root, exist_ok=True) + + return theme_root, samples_root, output_root, screenshot_root + + +def build_theme_previews(theme_root, samples_root, output_root, screenshot_root): + themes = [item for item in os.listdir(theme_root) if os.path.isdir(item) and not item.startswith((".", "_"))] + logger.info(f"processing {len(themes)} themes...") + + # launch web server for taking screenshots + server = subprocess.Popen( + ["python", "-m", "http.server", "-d", output_root], + stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + + fail = {} + success = {} + screenshot_processes = [] + + for theme in sorted(themes, key=lambda x: x.lower()): + theme_path = os.path.join(theme_root, theme) + if os.path.exists(os.path.join(theme_path, theme, "templates")): + # actual theme is in a subfolder + theme_path = os.path.join(theme_path, theme) + output_path = os.path.join(output_root, theme) + try: + process = subprocess.run([ + "pelican", + os.path.join(samples_root, "content"), + "--settings", os.path.join(samples_root, "pelican.conf.py"), + "--extra-settings", f"SITENAME=\"{theme} preview\"", + "--relative-urls", + "--theme-path", theme_path, + "--output", output_path, + "--ignore-cache", + "--delete-output-directory" + ], + check=True, capture_output=True, universal_newlines=True) + except subprocess.CalledProcessError as exc: + logger.error(f"[red]failed to generate : {theme}[/]", extra={"markup": True}) + fail[theme] = exc.stdout + continue + success[theme] = output_path + screenshot_path = os.path.join(screenshot_root, f"{theme}.png") + screenshot_processes.append( + subprocess.Popen( + ["shot-scraper", f"http://localhost:8000/{theme}", "-o", screenshot_path, "-w", "1280", "-h", "780", "--wait", "1000"], + stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + ) + logger.info(f"[green]successfully generated : {theme}[/]", extra={"markup": True}) + + # cleanup + logger.info("finalizing screenshots...") + for process in screenshot_processes: + process.wait() + server.terminate() + return success, fail + + +def write_index_files(output_root, success, fail): + logger.info("generating index files...") + with open(os.path.join(output_root, "index.html"), "w") as outfile: + outfile.write(HTML_HEADER) + for theme, theme_path in sorted(success.items(), key=lambda x: x[0].lower()): + outfile.write(f'
  • {theme}
  • ') + outfile.write(HTML_FOOTER.format(success=len(success), fail=len(fail))) + + with open(os.path.join(output_root, "failed.html"), "w") as outfile: + outfile.write(HTML_HEADER) + for theme, reason in sorted(fail.items(), key=lambda x: x[0].lower()): + outfile.write(f'
  • {theme}

    {reason}
  • ') + outfile.write(HTML_FOOTER.format(success=len(success), fail=len(fail))) + + logger.info(f"built {len(success)} themes") + logger.info(f"failed {len(fail)} themes") + + +def parse_args(argv=None): + parser = argparse.ArgumentParser() + parser.add_argument( + "--output", required=False, default="_output", + help="Output folder for generating the theme previews. Defaults to `_output` in themes folder root." + ) + parser.add_argument( + "--samples", required=False, default="_pelican/samples", + help="Sample website used to generate theme previews. Defaults to `_pelican/samples` in themes folder root." + ) + return parser.parse_args(argv) + + +def check_requirements(): + try: + proc = subprocess.run( + ["pelican", "--version"], + check=True, capture_output=True, universal_newlines=True + ) + logger.info("using pelican: {}".format(proc.stdout.strip())) + except subprocess.CalledProcessError: + raise RuntimeError("Requires `pelican`, see https://docs.getpelican.com") + try: + proc = subprocess.run( + ["shot-scraper", "--version"], + check=True, capture_output=True, universal_newlines=True + ) + logger.info("using shot-scraper: {}".format(proc.stdout.strip())) + except subprocess.CalledProcessError: + raise RuntimeError("Requires `shot-scraper`, see https://shot-scraper.data") + + +def main(argv=None): + check_requirements() + args = parse_args(argv) + theme_root, samples_root, output_root, screenshot_root = setup_folders(args) + success, fail = build_theme_previews(theme_root, samples_root, output_root, screenshot_root) + write_index_files(output_root, success, fail) + + +if __name__ == "__main__": + main() \ No newline at end of file From fa828224dda9b87282459e26873057a01385b19d Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Sun, 23 Jul 2023 08:40:50 +0200 Subject: [PATCH 3/3] CI: Sync built preview site to pelicanthemes.com --- .github/workflows/build-preview-site.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-preview-site.yml b/.github/workflows/build-preview-site.yml index 6dd2cc9c..2639c053 100644 --- a/.github/workflows/build-preview-site.yml +++ b/.github/workflows/build-preview-site.yml @@ -53,6 +53,17 @@ jobs: - name: Generate output run: python build-theme-previews.py + # Rsync to server hosting pelicanthemes.com + - name: Install SSH key + uses: shimataro/ssh-key-action@v2 + with: + key: ${{ secrets.SSH_PRIVATE_KEY }} + known_hosts: unnecessary + - name: Adding known hosts + run: ssh-keyscan -p 22 -H pelicanthemes.com >> ~/.ssh/known_hosts + - name: Deploy with rsync + run: rsync -avz ./_output/ deploy@pelicanthemes.com:~/roles/caddy/sites/pelicanthemes.com/ + # Deploy to Github Pages - name: Setup Pages uses: actions/configure-pages@v2 @@ -62,4 +73,4 @@ jobs: path: '_output' - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1 \ No newline at end of file + uses: actions/deploy-pages@v1