From 1b886c1f275fbf562106261e3602a2add7536865 Mon Sep 17 00:00:00 2001
From: Drew Devereux <drew.devereux@csiro.au>
Date: Mon, 12 Apr 2021 08:05:26 +0000
Subject: [PATCH] [MCCS-519] PlantUML / RTD support

---
 Makefile                                     |   9 ++-------
 docs/Dockerfile                              |   6 ++++++
 docs/requirements.txt                        |   1 +
 docs/source/State_Machine.rst                |   6 ++----
 docs/source/adminMode_state_machine.uml      |  11 +++++++++++
 docs/source/conf.py                          |   1 +
 docs/source/images/AdminModeStateMachine.png | Bin 8867 -> 0 bytes
 7 files changed, 23 insertions(+), 11 deletions(-)
 create mode 100644 docs/Dockerfile
 create mode 100644 docs/source/adminMode_state_machine.uml
 delete mode 100644 docs/source/images/AdminModeStateMachine.png

diff --git a/Makefile b/Makefile
index d120dd29..cf201f8e 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,6 @@ SHELL = /bin/bash
 DOCKER_REGISTRY_USER:=ska-telescope
 PROJECT = ska_tango_base
 IMAGE_FOR_DIAGRAMS = nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.3.1
-IMAGE_FOR_DOCS = sphinxdoc/sphinx:latest
 #
 # include makefile to pick up the standard Make targets, e.g., 'make build'
 # build, 'make push' docker push procedure, etc. The other Make targets
@@ -57,12 +56,8 @@ generate-diagrams-in-docker-internals:  ## Generate state machine diagrams (with
 	ls -lo /diagrams/docs/source/images/
 
 docs-in-docker: ## Generate docs inside a container
-	@docker run --rm -v $(PWD):/project $(IMAGE_FOR_DOCS) bash -c "cd /project && make docs-in-docker-internals"
-
-docs-in-docker-internals:  ## Generate docs (within a container!)
-	test -f /.dockerenv  # ensure running in docker container
-	python3 -m pip install -r /project/docs/requirements.txt
-	cd /project/docs && make clean && make html
+	@docker build -t ska_tango_base_docs_builder  . -f docs/Dockerfile
+	@docker run --rm -v $(PWD):/project --user $(id -u):$(id -g) ska_tango_base_docs_builder
 
 help:  ## show this help.
 	@grep -hE '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
diff --git a/docs/Dockerfile b/docs/Dockerfile
new file mode 100644
index 00000000..b7ad9a0c
--- /dev/null
+++ b/docs/Dockerfile
@@ -0,0 +1,6 @@
+FROM readthedocs/build:latest
+
+COPY docs/requirements.txt .
+RUN python3 -m pip install --exists-action=w --no-cache-dir --disable-pip-version-check -r requirements.txt
+
+ENTRYPOINT python3 -m sphinx -T -E -b html -d project/docs/build/doctrees project/docs/source project/docs/build/html
diff --git a/docs/requirements.txt b/docs/requirements.txt
index e4e2f8ea..a1912774 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,2 +1,3 @@
 Sphinx >= 3.5.0
 sphinx-rtd-theme >= 0.4.3
+sphinxcontrib-plantuml
diff --git a/docs/source/State_Machine.rst b/docs/source/State_Machine.rst
index ed542bfd..b8133a50 100644
--- a/docs/source/State_Machine.rst
+++ b/docs/source/State_Machine.rst
@@ -39,10 +39,8 @@ The admin mode state machine allows for
 
 Diagrams of the admin mode state machine are shown below.
 
-.. figure:: images/AdminModeStateMachine.png
-  :alt: Diagram of the admin mode state machine, as designed
-
-  Diagram of the admin mode state machine, as designed
+.. uml:: adminMode_state_machine.uml
+  :caption: Diagram of the admin mode state machine, as designed
 
 .. figure:: images/AdminModeStateMachine_autogenerated.png
   :alt: Diagram of the admin mode state machine, as implemented
diff --git a/docs/source/adminMode_state_machine.uml b/docs/source/adminMode_state_machine.uml
new file mode 100644
index 00000000..24945b2c
--- /dev/null
+++ b/docs/source/adminMode_state_machine.uml
@@ -0,0 +1,11 @@
+ONLINE --> ONLINE
+ONLINE <-right-> MAINTENANCE
+ONLINE <-down-> OFFLINE
+MAINTENANCE -> MAINTENANCE
+MAINTENANCE <-down-> OFFLINE
+OFFLINE -> OFFLINE
+OFFLINE <-down->NOT_FITTED
+OFFLINE <-down->RESERVED
+NOT_FITTED -> NOT_FITTED
+NOT_FITTED <-right->RESERVED
+RESERVED -> RESERVED
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 361c6f74..8871ddca 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -100,6 +100,7 @@ extensions = [
     'sphinx.ext.todo',
     'sphinx.ext.coverage',
     'sphinx.ext.viewcode',
+    'sphinxcontrib.plantuml'
 ]
 
 # Add any paths that contain templates here, relative to this directory.
diff --git a/docs/source/images/AdminModeStateMachine.png b/docs/source/images/AdminModeStateMachine.png
deleted file mode 100644
index 6351a89cf21b929414bfdaa2ca37028d77a32591..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 8867
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

-- 
GitLab