Updated build script
This commit is contained in:
parent
e716e48fa2
commit
e96c02531c
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,7 +6,6 @@ __pycache__
|
|||||||
# Output files
|
# Output files
|
||||||
main.pdf
|
main.pdf
|
||||||
**/build
|
**/build
|
||||||
_output
|
|
||||||
|
|
||||||
# TeX build files
|
# TeX build files
|
||||||
*.synctex.gz*
|
*.synctex.gz*
|
||||||
|
2
resources/scripts/.gitignore
vendored
Normal file
2
resources/scripts/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
output
|
||||||
|
output.zip
|
28
resources/scripts/Jenkinsfile
vendored
28
resources/scripts/Jenkinsfile
vendored
@ -1,28 +0,0 @@
|
|||||||
pipeline {
|
|
||||||
agent none
|
|
||||||
environment {
|
|
||||||
NC_CRED = credentials("nc-jenkins-cred")
|
|
||||||
NO_TEST = true
|
|
||||||
}
|
|
||||||
stages {
|
|
||||||
stage("Build") {
|
|
||||||
agent {
|
|
||||||
docker {
|
|
||||||
image "git.betalupi.com/mark/latex:latest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
// Keep these in one "sh" directive.
|
|
||||||
// Todo: create setup files so we don't
|
|
||||||
// have to pip install manually here.
|
|
||||||
// Maybe integrate python packages into the docker container?
|
|
||||||
sh '''
|
|
||||||
python -m venv venv
|
|
||||||
source venv/bin/activate
|
|
||||||
pip install tomli webdavclient3
|
|
||||||
python resources/scripts/build.py
|
|
||||||
'''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,155 +0,0 @@
|
|||||||
# Build script for CI.
|
|
||||||
# This file is run from the root of the repository
|
|
||||||
|
|
||||||
import os
|
|
||||||
import tomli
|
|
||||||
from pathlib import Path
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
from webdav3.client import Client
|
|
||||||
|
|
||||||
import helpers.tex as tex
|
|
||||||
|
|
||||||
conf_path = "resources/scripts/build.toml"
|
|
||||||
|
|
||||||
# Prepare envvars
|
|
||||||
e = os.environ.copy()
|
|
||||||
e["TEXINPUTS"] = f"::/usr/share/texmf-dist/tex//"
|
|
||||||
print(Path.cwd())
|
|
||||||
|
|
||||||
# If true, rebuild everything
|
|
||||||
# without checking for changes.
|
|
||||||
# Currently unused.
|
|
||||||
if "FORCE_ALL" in e:
|
|
||||||
force_all = e["FORCE_ALL"] == "true"
|
|
||||||
else:
|
|
||||||
force_all = False
|
|
||||||
|
|
||||||
if "NO_TEST" in e:
|
|
||||||
test = e["NO_TEST"] == "false"
|
|
||||||
else:
|
|
||||||
test = True
|
|
||||||
|
|
||||||
|
|
||||||
# Used only for debug
|
|
||||||
class FakeClient:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def mkdir(self, path):
|
|
||||||
print(f"[Dry run] Making dir {path}")
|
|
||||||
|
|
||||||
def upload_sync(self, local_path, remote_path):
|
|
||||||
print(f"[Dry run] Synced {local_path} to {remote_path}")
|
|
||||||
|
|
||||||
def clean(self, path):
|
|
||||||
print(f"[Dry run] Cleaning {path}")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Load configuration
|
|
||||||
with open(conf_path, mode="rb") as fp:
|
|
||||||
config = tomli.load(fp)
|
|
||||||
|
|
||||||
# Prepare directories
|
|
||||||
builddir = Path().absolute() / config["core"]["build_dir"]
|
|
||||||
output = Path().absolute() / config["core"]["output_dir"]
|
|
||||||
output.mkdir(parents = True, exist_ok = True)
|
|
||||||
builddir.mkdir(parents = True, exist_ok = True)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if not test:
|
|
||||||
# Connect to webdav
|
|
||||||
client = Client({
|
|
||||||
"webdav_login": e["NC_CRED_USR"],
|
|
||||||
"webdav_password": e["NC_CRED_PSW"],
|
|
||||||
"webdav_hostname": e["DAV_HOSTNAME"], # https://host:port
|
|
||||||
"webdav_root": e["DAV_ROOT"] # the rest of the url
|
|
||||||
# client.list() will break if we do not seperate the hostname
|
|
||||||
# and the root path.
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
client = FakeClient()
|
|
||||||
|
|
||||||
|
|
||||||
def upload_dir(local_path: Path):
|
|
||||||
for p in local_path.rglob("*"):
|
|
||||||
r = p.relative_to(output)
|
|
||||||
if p.is_dir():
|
|
||||||
client.mkdir(str(r))
|
|
||||||
|
|
||||||
elif p.is_file():
|
|
||||||
client.upload_sync( # type: ignore
|
|
||||||
remote_path = str(r),
|
|
||||||
local_path = p
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Print envvars for debug
|
|
||||||
#print(e)
|
|
||||||
|
|
||||||
|
|
||||||
for i, item in enumerate(config["dir-of-dirs"]):
|
|
||||||
p = Path(item["path"])
|
|
||||||
|
|
||||||
for s in p.iterdir():
|
|
||||||
# s: path to directory,
|
|
||||||
# # relative to repo root
|
|
||||||
if not s.is_dir():
|
|
||||||
continue
|
|
||||||
|
|
||||||
print(f"Building {s}/main.tex")
|
|
||||||
|
|
||||||
# Make pdf
|
|
||||||
pdf_nosolutions = tex.build(
|
|
||||||
s,
|
|
||||||
mainfile = "main.tex",
|
|
||||||
jobname = f"{i}-nosols",
|
|
||||||
build_dir = builddir,
|
|
||||||
solutions = False,
|
|
||||||
|
|
||||||
env = e,
|
|
||||||
test = test
|
|
||||||
)
|
|
||||||
|
|
||||||
pdf_solutions = tex.build(
|
|
||||||
s,
|
|
||||||
mainfile = "main.tex",
|
|
||||||
jobname = f"{i}-sols",
|
|
||||||
build_dir = builddir,
|
|
||||||
solutions = True,
|
|
||||||
|
|
||||||
env = e,
|
|
||||||
test = test
|
|
||||||
)
|
|
||||||
|
|
||||||
target_dir = output / s.parent
|
|
||||||
target_dir.mkdir(parents = True, exist_ok = True)
|
|
||||||
|
|
||||||
shutil.copy(
|
|
||||||
pdf_nosolutions,
|
|
||||||
target_dir / (s.stem + ".pdf")
|
|
||||||
)
|
|
||||||
|
|
||||||
shutil.copy(
|
|
||||||
pdf_solutions,
|
|
||||||
target_dir / (s.stem + ".sols.pdf")
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: this breaks when the output directory is empty.
|
|
||||||
# Fix it eventually.
|
|
||||||
if not test:
|
|
||||||
# Delete old files
|
|
||||||
for i in client.list():
|
|
||||||
if i.endswith("/"):
|
|
||||||
i = i[:-1]
|
|
||||||
client.clean(i)
|
|
||||||
|
|
||||||
upload_dir(output)
|
|
||||||
|
|
||||||
# Remove output files so they don't persist
|
|
||||||
# shutil.rmtree(output)
|
|
||||||
# Shouldn't be necessary if you tell
|
|
||||||
# jenkins to "clean before checkout."
|
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
START=$(pwd)
|
START=$(pwd)
|
||||||
OUTPUT="${START}/_output"
|
OUT_SUBDIR="output"
|
||||||
|
|
||||||
function build() {
|
function build() {
|
||||||
local DIR="$(dirname "${1}")"
|
local DIR="$(dirname "${1}")"
|
||||||
@ -30,7 +30,7 @@ function build() {
|
|||||||
|
|
||||||
for d in ../../Advanced/*/ ; do
|
for d in ../../Advanced/*/ ; do
|
||||||
DIR=$(realpath "${d}")
|
DIR=$(realpath "${d}")
|
||||||
OUTPUT="${START}/_output/Advanced"
|
OUTPUT="${START}/${OUT_SUBDIR}/Advanced"
|
||||||
mkdir -p "${OUTPUT}"
|
mkdir -p "${OUTPUT}"
|
||||||
|
|
||||||
build "${DIR}/main.tex"
|
build "${DIR}/main.tex"
|
||||||
@ -38,8 +38,11 @@ done
|
|||||||
|
|
||||||
for d in ../../Intermediate/*/ ; do
|
for d in ../../Intermediate/*/ ; do
|
||||||
DIR=$(realpath "${d}")
|
DIR=$(realpath "${d}")
|
||||||
OUTPUT="${START}/_output/Intermediate"
|
OUTPUT="${START}/${OUT_SUBDIR}/Intermediate"
|
||||||
mkdir -p "${OUTPUT}"
|
mkdir -p "${OUTPUT}"
|
||||||
|
|
||||||
build "${DIR}/main.tex"
|
build "${DIR}/main.tex"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
zip -FSrj output.zip "${OUT_SUBDIR}/*"
|
@ -1,12 +0,0 @@
|
|||||||
# All paths are relative to the root of this repository.
|
|
||||||
|
|
||||||
[core]
|
|
||||||
build_dir = "_build"
|
|
||||||
output_dir = "_output"
|
|
||||||
|
|
||||||
|
|
||||||
[[dir-of-dirs]]
|
|
||||||
path = "Advanced"
|
|
||||||
|
|
||||||
[[dir-of-dirs]]
|
|
||||||
path = "Intermediate"
|
|
@ -1,60 +0,0 @@
|
|||||||
from pathlib import Path
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
def build(
|
|
||||||
path: Path,
|
|
||||||
*,
|
|
||||||
solutions: bool = True,
|
|
||||||
mainfile: str = "main.tex",
|
|
||||||
jobname: str = "main",
|
|
||||||
build_dir: Path = Path("build"),
|
|
||||||
|
|
||||||
test = False,
|
|
||||||
env: dict = {},
|
|
||||||
) -> Path:
|
|
||||||
"""
|
|
||||||
Build a directory using XeTeX.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
path (Path): directory to build
|
|
||||||
solutions (bool, optional): Create a handout with solutions? Defaults to True.
|
|
||||||
mainfile (str, optional): Path to main TeX file, relative to path. Defaults to "main.tex".
|
|
||||||
jobname (str, optional): TeX job name. Defaults to "main".
|
|
||||||
build_dir (Path, optional): Where to place build files. Defaults to Path("build").
|
|
||||||
|
|
||||||
test (bool, optional): If true, dry run. Defaults to False.
|
|
||||||
env (dict): Dictionary of environment variables.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Path: Absolute path to output pdf.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Make temporary file for TeX build arg hack
|
|
||||||
if solutions:
|
|
||||||
with (build_dir/"tmp.tex").open("w") as f:
|
|
||||||
f.write("\\def\\argYesSolutions{1}\\input{" + mainfile + "}")
|
|
||||||
else:
|
|
||||||
with (build_dir/"tmp.tex").open("w") as f:
|
|
||||||
f.write("\\def\\argNoSolutions{1}\\input{" + mainfile + "}")
|
|
||||||
|
|
||||||
cmd = subprocess.run([
|
|
||||||
"latexmk",
|
|
||||||
"-interaction=nonstopmode",
|
|
||||||
"-file-line-error",
|
|
||||||
f"-outdir={build_dir}",
|
|
||||||
"-xelatex",
|
|
||||||
f"-jobname={jobname}",
|
|
||||||
build_dir/"tmp.tex"
|
|
||||||
],
|
|
||||||
cwd = path,
|
|
||||||
env = env,
|
|
||||||
stdout = None if test else subprocess.DEVNULL,
|
|
||||||
stderr = None if test else subprocess.DEVNULL
|
|
||||||
)
|
|
||||||
|
|
||||||
assert cmd.returncode == 0
|
|
||||||
|
|
||||||
# Remove tmp file
|
|
||||||
(build_dir / "tmp.tex").unlink()
|
|
||||||
|
|
||||||
return build_dir / f"{jobname}.pdf"
|
|
Loading…
x
Reference in New Issue
Block a user