diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aadc62f..a4415d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,8 @@ jobs: sudo apt install --yes \ texlive texlive-xetex \ texlive-games texlive-fonts-extra texlive-latex-extra \ - texlive-pictures texlive-pstricks + texlive-pictures texlive-pstricks \ + python3-requests # Typst isn't packaged, and manual download gives us # more control anyway. @@ -85,3 +86,12 @@ jobs: name: "Build output" path: "output/*" retention-days: 10 + + - name: "Publish package" + run: | + PUBLISH_USER="${{ secrets.PUBLISH_USER }}" \ + PUBLISH_KEY="${{ secrets.PUBLISH_KEY }}" \ + VERSION="${{ github.sha }}" \ + python tools/build/publish.py + + diff --git a/tools/build/main.py b/tools/build/main.py index c33bfbd..04ea0af 100644 --- a/tools/build/main.py +++ b/tools/build/main.py @@ -126,6 +126,9 @@ def build_typst(source_dir: Path, out_subdir: Path) -> IndexEntry | None: return None meta = read_meta_toml(meta_path) + handout_file = sanitize_file_name(f"{meta['title']}.pdf") + solutions_file = sanitize_file_name(f"{meta['title']}.sols.pdf") + # Do nothing if not published if not meta["publish_handout"]: return None @@ -136,7 +139,6 @@ def build_typst(source_dir: Path, out_subdir: Path) -> IndexEntry | None: out = OUT_DIR / out_subdir out.mkdir(parents=True, exist_ok=True) - file_name = sanitize_file_name(f"{meta['title']}.pdf") res = subprocess.run( [ TYPST_PATH, @@ -145,7 +147,7 @@ def build_typst(source_dir: Path, out_subdir: Path) -> IndexEntry | None: "main.typ", "--input", "show_solutions=false", - f"{out}/{file_name}", + f"{out}/{handout_file}", ], cwd=source_dir, stdout=subprocess.PIPE, @@ -158,14 +160,13 @@ def build_typst(source_dir: Path, out_subdir: Path) -> IndexEntry | None: # Build solutions if meta["publish_solutions"]: log(f"Building typst (solutions): {source_dir}") - file_name = sanitize_file_name(f"{meta['title']}.sols.pdf") res = subprocess.run( [ TYPST_PATH, "compile", "--ignore-system-fonts", "main.typ", - f"{out}/{file_name}", + f"{out}/{solutions_file}", ], cwd=source_dir, stdout=subprocess.PIPE, @@ -178,9 +179,9 @@ def build_typst(source_dir: Path, out_subdir: Path) -> IndexEntry | None: return { "title": meta["title"], "group": str(out_subdir), - "handout_file": f"{out_subdir}/{meta['title']}.pdf", + "handout_file": str(out/handout_file), "solutions_file": ( - f"{out_subdir}/{meta['title']}.sols.pdf" + str(out/solutions_file) if meta["publish_solutions"] else None ), @@ -198,6 +199,9 @@ def build_xetex(source_dir: Path, out_subdir: Path) -> IndexEntry | None: return None meta = read_meta_toml(meta_path) + handout_file = sanitize_file_name(f"{meta['title']}.pdf") + solutions_file = sanitize_file_name(f"{meta['title']}.sols.pdf") + # Do nothing if not published if not meta["publish_handout"]: return None @@ -219,9 +223,8 @@ def build_xetex(source_dir: Path, out_subdir: Path) -> IndexEntry | None: stderr=subprocess.PIPE, ) - file_name = sanitize_file_name(f"{meta['title']}.pdf") try: - shutil.copy(source_dir / "main.pdf", f"{out}/{file_name}") + shutil.copy(source_dir / "main.pdf", f"{out}/{handout_file}") except Exception as e: log(f"Error: {e}") log_error(res) @@ -243,9 +246,8 @@ def build_xetex(source_dir: Path, out_subdir: Path) -> IndexEntry | None: stderr=subprocess.PIPE, ) - file_name = sanitize_file_name(f"{meta['title']}.sols.pdf") try: - shutil.copy(source_dir / "main.pdf", f"{out}/{file_name}") + shutil.copy(source_dir / "main.pdf", f"{out}/{solutions_file}") except Exception as e: log(f"Error: {e}") log_error(res) @@ -256,9 +258,9 @@ def build_xetex(source_dir: Path, out_subdir: Path) -> IndexEntry | None: return { "title": meta["title"], "group": str(out_subdir), - "handout_file": f"{out_subdir}/{meta['title']}.pdf", + "handout_file": str(out/handout_file), "solutions_file": ( - f"{out_subdir}/{meta['title']}.sols.pdf" + str(out/solutions_file) if meta["publish_solutions"] else None ), diff --git a/tools/build/publish.py b/tools/build/publish.py new file mode 100644 index 0000000..89e0984 --- /dev/null +++ b/tools/build/publish.py @@ -0,0 +1,58 @@ +from typing import TypedDict +from pathlib import Path +import requests +import shutil +import json +import os +from requests.auth import HTTPBasicAuth + +URL="https://git.betalupi.com" +USER = os.environ['USER'] +PACKAGE = "ormc-handouts" +VERSION = os.environ['VERSION'] +AUTH = HTTPBasicAuth(USER, os.environ['PUBLISH_KEY']) + +ROOT: Path = Path(os.getcwd()) +SRC_DIR: Path = ROOT / "output" + +def log(msg): + print(f"[PUBLISH.PY] {msg}") + +log(f"Running in {ROOT}") +if not ROOT.is_dir(): + log("Root is not a directory, cannot continue") + exit(1) + +log(f"Output dir is {SRC_DIR}") +if not SRC_DIR.exists(): + log("Output dir doesn't exist, cannot continue") + exit(1) + +IndexEntry = TypedDict( + "IndexEntry", + {"title": str, "group": str, "handout_file": str, "solutions_file": str | None}, +) + + +index = SRC_DIR / "index.json" +with index.open("r") as f: + index = json.load(f) + +for handout in index: + title = handout["title"] + group = handout["group"] + h_file = SRC_DIR/handout["handout_file"] + s_file = SRC_DIR/handout["handout_file"] + + target = f"{group} - {title}.pdf" + requests.put( + f"{URL}/api/packages/{USER}/generic/{PACKAGE}/{VERSION}/{target}", + auth=AUTH, data=h_file.open('rb').read()) + + if s_file is not None: + target = f"{group} - {title}.sols.pdf" + requests.put( + f"{URL}/api/packages/{USER}/generic/{PACKAGE}/{VERSION}/{target}", + auth=AUTH, data=s_file.open('rb').read()) + + log(f"Published {title}") \ No newline at end of file