Merge branch 'release/0.2'

This commit is contained in:
Jörn-Michael Miehe 2019-09-24 11:40:51 +02:00
commit d8ee619d60
2 changed files with 93 additions and 49 deletions

100
README.md
View file

@ -1,54 +1,96 @@
# autodoc
[`autodoc`](https://github.com/ldericher/autodoc) is a simple [CI](https://en.wikipedia.org/wiki/Continuous_integration) script, primarily aimed at document creation.
[`autodoc`](https://github.com/ldericher/autodoc) is a simple [CI](https://en.wikipedia.org/wiki/Continuous_integration) system optimized for document creation.
## Basics
In general, any file-sharing solution -- preferably on top of `docker-compose` -- can be made into an automatic document distribution system by adding an `autodoc` instance.
`autodoc` relies upon [inotify-tools](https://github.com/rvoicilas/inotify-tools) to recursively watch a Linux file system directory.
## Quick Start Guide using Docker
For each file change, `autodoc` searches corresponding build instruction files (Makefiles etc.) and kicks off build processes accordingly.
The `autodoc` image [available on Docker Hub](https://hub.docker.com/r/ldericher/autodoc) is based on [pandocker](https://hub.docker.com/r/ldericher/pandocker) providing Ubuntu's TeXlive `LaTeX` and `pandoc` in a simple box.
## Usage
01. Install [Docker CE](https://docs.docker.com/install/)
`autodoc` is designed to run in a server-side, containerized context.
01. Clone or download the `autodoc` repository, open a terminal inside the [example_docs](https://github.com/ldericher/autodoc/tree/master/example_docs) directory
### Deploy a container
01. Deploy an `autodoc` container:
`autodoc` can be pulled from the docker hub using `docker pull ldericher/autodoc`.
```bash
docker run --rm -it \
--volume "${PWD}":/docs \
--user "$(id -u):$(id -g)" \
ldericher/autodoc
```
When deploying an `autodoc` container, mount your document root to `/docs`. You *should* also set the container's UID and GID.
The contents of the directory are now being watched by `autodoc`!
#### Included software
When deploying an `autodoc` container, just mount your document root to `/docs`. You *should* also set the container's UID and GID. These are seen above.
TODO `ldericher/autodoc` contains `pandoc`.
01. Edit some stuff, save -- and watch the magic happen (and the terminal output).
#### tl;dr
On each file change, `autodoc` searches relevant build instruction files (Makefiles etc.) and kicks off build processes accordingly.
Deploy an `autodoc` instance in your current working dir:
### How *not* to use `autodoc`
docker run --name autodoc -d -v "${PWD}":/docs --user "$(id -u):$(id -g)" ldericher/autodoc
`autodoc` is **not** a solution for Continuous Integration of large scale systems software! `autodoc` excels at building a large number of independent, small files.
### Automating builds
### Deploying without Docker
Example automated builds can be found [here](https://github.com/ldericher/autodoc/tree/master/example_docs).
`autodoc` only hard-depends on `inotifywait` from [inotify-tools](https://github.com/rvoicilas/inotify-tools) to recursively watch Linux file system directories.
In general, just put a build instruction file into any (sub-)directory watched by `autodoc` and add your source files.
You will usually want to install a `LaTeX` distribution and setup `pandoc`.
## Prime use case: Nextcloud
Nextcloud is a "safe home for all your data" that can [easily be deployed using docker-compose](https://hub.docker.com/_/nextcloud).
Add an `autodoc` container to create directories where PDFs are automatically held up to date for all your documents. This extends upon the "[Base version - apache](https://hub.docker.com/_/nextcloud#base-version---apache)" of the Nextcloud compose deployment.
```yaml
version: '2'
volumes:
documents:
services:
app:
volumes:
- documents:/opt/autodoc
autodoc:
restart: always
image: ldericher/autodoc
user: "UID:GID"
volumes:
- documents:/docs
```
The "user" key should be set to the same numeric IDs used for the nextcloud worker processes! To find the right IDs, issue `docker-compose exec app sh -c 'id -u www-data; id -g www-data'`.
For the apache containers, this should evaluate to "33:33".
To begin, add the mounted `/opt/autodoc` as a 'local type' external storage to your Nextcloud instance.
You might need to setup the permissions on your new volume using `docker-compose exec app chown -R www-data:www-data /opt/autodoc`.
## Concept: Source patterns
To avoid unnecessary rebuilds and self-triggering, `autodoc` uses "source patterns" to filter for the relevant build instructions.
A source pattern is a `bash` regular expression matching any filename that should be regarded as a "source file" to the build instruction file.
For instance, if a Makefile instructs how to build from Markdown source files, that Makefile's source pattern should likely be `\.md$`.
## Creating an automated build
In general, just put your source files into any (sub-)directory watched by `autodoc`. Add a build instruction file.
On each file change, its containing directory is searched for a build instruction file. Watched parent directories are also probed for further build instructions.
Every relevant instruction file will be executed as found.
You may combine build instruction systems to your liking.
#### SRCPAT concept, "relevant" build instructions
## Build instruction systems
To avoid unnecessary rebuilds and self-triggering, `autodoc` uses "source patterns" to decide which build instructions are relevant.
### GNU Make (Makefiles)
For instance, if a build instruction file describes building anything from Markdown files, its source pattern should be something like `\.md$` to match files with ".md" as last extension. Source patterns are `bash` regular expressions.
#### GNU Make (Makefiles)
`autodoc` supports standard Makefiles.
`Makefile`s must contain a SRCPAT annotation comment as follows, where `<regex>` is the source pattern as above.
`autodoc` supports GNU Makefiles.
However, Makefiles must contain a SRCPAT annotation comment as follows, where `<regex>` is a source pattern as above.
```Makefile
#@SRCPAT <regex>
@ -56,16 +98,10 @@ For instance, if a build instruction file describes building anything from Markd
If there are multiple SRCPAT annotations, the lowermost one will be used.
##### Advanced options
You may add a PHONY target "autodoc" which will be built *instead* of the default target.
You *may* add a PHONY target "autodoc" which will be built *instead* of the default target.
```Makefile
.PHONY: autodoc
autodoc:
@echo "Hello World!"
```
## What not to use `autodoc` for
`autodoc` excels at building a large number of independent small files. It is **not** a solution for Continuous Integration of large scale software systems!

View file

@ -4,28 +4,37 @@
g_watchroot="$(readlink -f "${1:-.}")"
# compile using bare make command
do_make() { # $1:DIR $2:OBJECT
do_make() { # $1:DIR $2:MAKEFILE $3:OBJECT
# extract params
local dir="$1"
local object="$2"
local makefile="$2"
local object="$3"
# extract Makefile 'source pattern'
local srcpat="$(grep -E "^#@SRCPAT" "${dir}/Makefile" | tail -n 1 | sed -r "s/^#@SRCPAT\s+//")"
# check Makefile 'source pattern'
local srcpat="$(grep -E "^#@SRCPAT" "${dir}/${makefile}" | tail -n 1 | sed -r "s/^#@SRCPAT\s+//")"
if [ -z "${srcpat}" ]; then
echo "Empty source pattern! Makefile needs '#@SRCPAT' annotation!"
echo -n "Empty source pattern, check '#@SRCPAT' annotation! "
return 1
elif [[ "${object}" =~ ${srcpat} ]]; then
# check for autodoc target
local target="$(grep -E "^autodoc:" "${dir}/Makefile" | sed -r "s/:.*$//")"
local target="${target:-all}"
local target="$(grep -E "^autodoc:" "${dir}/${makefile}" | sed -r "s/:.*$//")"
echo "SRCPAT OK, building '${target}'."
make --no-print-directory -C "${dir}" -j "${target}"
if [ -z "${target}" ]; then
echo "Running 'make'. "
else
echo "Making '${target}'. "
fi
make --no-print-directory -C "${dir}" -j ${target}
else
echo "SRCPAT mismatch '${srcpat}'."
echo -n "SRCPAT '${srcpat}' mismatch. "
return 1
fi
return 0
}
# compile a directory
@ -39,16 +48,15 @@ do_compile() { # $1:DIR $2:OBJECT $3:DONE
if [ -r "${dir}/Makefile" ]; then
# Makefile found
echo -n "Using '${dir}/Makefile'. "
do_make "${dir}" "${object}"
local done="1"
echo -n "Found '${dir}/Makefile': "
do_make "${dir}" "Makefile" "${object}" \
&& local done="1"
fi
# search parent dir for more build instructions
if [ "${dir}" != "${g_watchroot}" ]; then
# never leave $g_watchroot
local dir="$(dirname "${dir}")"
do_compile "${dir}" "${object}" "${done}"
if [ "${dir}" != "${g_watchroot}" ]; then
# search parent dir for more build instructions
do_compile "$(dirname "${dir}")" "${object}" "${done}"
elif [ "${done}" == "0" ]; then
# hit $g_watchroot