The above instructions allow to build manually but otherwise it is automatically tested, built and uploaded to pypi.org using _Travis CI_ on each push to GitHub (see [`.travis.yml`](.travis.yml)).
## Docker build
There are several Dockerfiles, each made for specific use cases (see [README.md](README.md#Docker-usage)).
They all have [multiple stages](https://docs.docker.com/develop/develop-images/multistage-build/).
`debian.Dockerfile` is quite straight. It builds using *pip* in one stage and copies the resulting *wheels* into the final one.
`debian-signal.Dockerfile` is more complex because it needs to address :
- including both Python and Java while keeping the image size small
- compiling native dependencies (both for _signal-cli_ and _qr_)
- circumventing a number of bugs in multiarch building
`debian-alpine.Dockerfile` produces smaller images but may not be as much portable than debian ones and misses Signal support for now.
Note that the _signal-cli_ backend needs a _Java_ runtime environment, and also _rust_ dependencies to support Signal's group V2. This approximately doubles the size of the images and almost ruins the advantage of alpine over debian...
Those images are limited on each OS (debian+glibc / alpine+musl) to CPU architectures which :
1. have base images (python, openjdk, rust)
2. have Python dependencies have _wheels_ or are able to build them
3. can build libzkgroup (native dependencies for signal)
4. have the required packages to build
At the time of writing, support is dropped for :
-`linux/s390x` : lack of _python:3_ image (at least)
-`linux/riscv64` : lack of _python:3_ image (at least)
- Signal backend on `linux/arm*`_for Alpine variants_ : lack of JRE binaries
All images have all the bots inside (as they would otherwise only differ by one script from each other).
The [`docker-entrypoint.sh`](docker/docker-entrypoint.sh) script takes the name of the bot to invoke as its first argument, then its own options and finally the bot's arguments.
docker run --rm -it -v "$(pwd)/tests:/etc/nicobot" nicolabs/nicobot:debian askbot -c /etc/nicobot/askbot-sample-conf/config.yml
### Automation for Docker Hub
_Github actions_ are currently used (see [`.github/workflows/dockerhub.yml`](.github/workflows/dockerhub.yml) to automatically build and push the images to [Docker Hub](https://hub.docker.com/r/nicolabs/nicobot) so they are available whenever commits are pushed to the _master_ branch :
1. A *Github Action* is triggered on each push to [the central repo](https://github.com/nicolabs/nicobot)
2. All images are built in order using caching (see [.github/workflows/dockerhub.yml](.github/workflows/dockerhub.yml))
3. Images are uploaded to [Docker Hub](https://hub.docker.com/repository/docker/nicolabs/nicobot)
### Docker build process overview
This is the view from the **master** branch on this repository.
It emphasizes *FROM* and *COPY* relations between the images (base and stages).
[The open issues labelled with *docker*](https://github.com/nicolabs/nicobot/labels/docker) should reference the reasons for missing arch / configuration.
The `--version` command-line option that displays the bots' version relies on _setuptools_scm_, which extracts it from the underlying git metadata.
This is convenient because the developer does not have to manually update the version (or forget to do it), however it either requires the version to be fixed inside a Python module or the `.git` directory to be present.
There were several options among which the following one has been retained :
1. Running `setup.py` creates / updates the version inside the `version.py` file
- [Language Translator API documentation](https://cloud.ibm.com/apidocs/language-translator)
### Signal
- [Signal home](https://signal.org/)
- [signal-cli man page](https://github.com/AsamK/signal-cli/blob/master/man/signal-cli.1.adoc)
### Jabber
- Official XMPP libraries : https://xmpp.org/software/libraries.html
- OMEMO compatible clients : https://omemo.top/
- [OMEMO official Python library](https://github.com/omemo/python-omemo) : looks very immature
- *Gaijim*, a Windows/MacOS/Linux XMPP client with OMEMO support : [gajim.org](https://gajim.org/) | [dev.gajim.org/gajim](https://dev.gajim.org/gajim)
- *Conversations*, an Android XMPP client with OMEMO support and paid hosting : https://conversations.im
### Python libraries
- [xmpppy](https://github.com/xmpppy/xmpppy) : this library is very easy to use but it does allow easy access to thread or timestamp, and no OMEMO...
- [github.com/horazont/aioxmpp](https://github.com/horazont/aioxmpp) : officially referenced library from xmpp.org, seems the most complete but misses practical introduction and [does not provide OMEMO OOTB](https://github.com/horazont/aioxmpp/issues/338).
- [slixmpp](https://lab.louiz.org/poezio/slixmpp) : seems like a cool library too and pretends to require minimal dependencies ; plus it [supports OMEMO](https://lab.louiz.org/poezio/slixmpp-omemo/) so it's the winner. [API doc](https://slixmpp.readthedocs.io/).
### Dockerfile
- [Best practices for writing Dockerfiles](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)
- [Docker development best practices](https://docs.docker.com/develop/dev-best-practices/)
- [phusion/baseimage-docker @ github - not used in the end, because not so portable](https://github.com/phusion/baseimage-docker)
- [Azul JDK - not used in the end because not better than openjdk](http://docs.azul.com/zulu/zuludocs/ZuluUserGuide/PrepareZuluPlatform/AttachAPTRepositoryUbuntuOrDebianSys.htm)
- [rappdw/docker-java-python image - not used because only for amd64](https://hub.docker.com/r/rappdw/docker-java-python)
- [Use OpenJDK builds provided by jdk.java.net?](https://github.com/docker-library/openjdk/issues/212)
- [How to install tzdata on a ubuntu docker image?](https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image)
### Multiarch & native dependencies
- [docker.com - Automatic platform ARGs in the global scope](https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope)
- [How to build ARMv6 and ARMv7 in the same manifest file. (Compatible tag for ARMv7, ARMv6, ARM64 and AMD64)](https://github.com/KEINOS/Dockerfile_of_Alpine/issues/3)
- [The "dpkg-split: No such file or directory" bug](https://github.com/docker/buildx/issues/495)
- [The "Command '('lsb_release', '-a')' returned non-zero exit status 1" bug](https://github.com/docker/buildx/issues/493)
- [pip is showing error 'lsb_release -a' returned non-zero exit status 1](https://stackoverflow.com/questions/44967202/pip-is-showing-error-lsb-release-a-returned-non-zero-exit-status-1)
### Rust
- [Compiling with rust](https://www.rust-lang.org/tools/install)
- [Packaging a Rust web service using Docker](https://blog.logrocket.com/packaging-a-rust-web-service-using-docker/)
- [docker/buildx - Value too large for defined data type](https://github.com/docker/buildx/issues/395)
<!-- MARKDOWN LINKS & IMAGES ; thks to https://github.com/othneildrew/Best-README-Template -->