Skip to content

Commit

Permalink
Fix miscellaneous issues
Browse files Browse the repository at this point in the history
  • Loading branch information
hunyadi committed Sep 30, 2024
1 parent 4b18d85 commit e2b6389
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 39 deletions.
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
__pycache__
/.env
/.envrc
/.idea
/.mypy_cache
/.venv
/*.egg-info
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
__pycache__
/.env
/.envrc
/.idea
/.mypy_cache
/.venv
/dist
/*.egg-info
.envrc
.venv
.idea
24 changes: 19 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,33 @@ FROM python:${PYTHON_VERSION}-alpine as builder

COPY ./ ./

RUN python3 -m pip install --upgrade pip && \
pip install build && \
python -m build --wheel
RUN PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --upgrade pip && \
pip install build
RUN python -m build --wheel

FROM python:${PYTHON_VERSION}-alpine as host

RUN apk add --update nodejs npm && \
npm install -g @mermaid-js/mermaid-cli
# set environment for @mermaid-js/mermaid-cli
# https://github.com/mermaid-js/mermaid-cli/blob/master/Dockerfile
ENV CHROME_BIN="/usr/bin/chromium-browser" \
PUPPETEER_SKIP_DOWNLOAD="true"

# install dependencies for @mermaid-js/mermaid-cli
# https://github.com/mermaid-js/mermaid-cli/blob/master/install-dependencies.sh
RUN apk add chromium font-noto-cjk font-noto-emoji terminus-font ttf-dejavu ttf-freefont ttf-font-awesome ttf-inconsolata ttf-linux-libertine \
&& fc-cache -f

RUN apk add --update nodejs npm
RUN addgroup md2conf && adduser -D -G md2conf md2conf
USER md2conf
WORKDIR /home/md2conf
RUN npm install @mermaid-js/mermaid-cli

FROM host as runner

COPY --from=builder /dist/*.whl dist/

RUN python3 -m pip install `ls -1 dist/*.whl`

WORKDIR /data
ENTRYPOINT ["python3", "-m", "md2conf"]
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,27 @@ options:
--webui-links Enable Confluence Web UI links.
```

### Using the docker container
### Using the Docker container

You can run the docker container via `docker run` or via `Dockerfile`. Either can accept the environment variables or arguments similar to the Python options. The final argument `./` corresponds to `mdpath` in the command-line utility.
You can run the Docker container via `docker run` or via `Dockerfile`. Either can accept the environment variables or arguments similar to the Python options. The final argument `./` corresponds to `mdpath` in the command-line utility.

With `docker run`, you can pass Confluence domain, user, API and space key directly to `docker run`:

```sh
docker run --rm --name md2conf hunyadi/md2conf -d instructure.atlassian.net -u levente.hunyadi@instructure.com -a 0123456789abcdef -s DAP ./
docker run --rm --name md2conf -v $(pwd):/data hunyadi/md2conf -d instructure.atlassian.net -u levente.hunyadi@instructure.com -a 0123456789abcdef -s DAP ./
```

Note that the entry point for the docker container's base image is `ENTRYPOINT ["python3", "-m", "md2conf"]`.
Alternatively, you can use a separate file `.env` to pass these parameters as environment variables:

```sh
docker run --rm --env-file .env --name md2conf -v $(pwd):/data hunyadi/md2conf ./
```

In each case, `-v $(pwd):/data` maps the current directory to Docker container's `WORKDIR` such *md2conf* can scan files and directories in the local file system.

Note that the entry point for the Docker container's base image is `ENTRYPOINT ["python3", "-m", "md2conf"]`.

With the `Dockerfile` approach, you can extend the base image:

```Dockerfile
FROM hunyadi/md2conf:latest
Expand Down
2 changes: 1 addition & 1 deletion md2conf/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def _get_or_create_page(
else:
if parent_id is None:
raise ValueError(
"expected: Confluence page ID to act as parent for Markdown files with no linked Confluence page"
f"expected: parent page ID for Markdown file with no linked Confluence page: {absolute_path}"
)

confluence_page = self._create_page(
Expand Down
60 changes: 41 additions & 19 deletions md2conf/mermaid.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
import logging
import os
import os.path
import shutil
import subprocess
from typing import Literal

LOGGER = logging.getLogger(__name__)


def is_docker() -> bool:
"True if the application is running in a Docker container."

return (
os.environ.get("CHROME_BIN") == "/usr/bin/chromium-browser"
and os.environ.get("PUPPETEER_SKIP_DOWNLOAD") == "true"
)


def get_mmdc() -> str:
"Path to the Mermaid diagram converter."

if is_docker():
return "/home/md2conf/node_modules/.bin/mmdc"
elif os.name == "nt":
return "mmdc.cmd"
else:
return "mmdc"


def has_mmdc() -> bool:
"True if Mermaid diagram converter is available on the OS."

if os.name == "nt":
executable = "mmdc.cmd"
else:
executable = "mmdc"
executable = get_mmdc()
return shutil.which(executable) is not None


Expand All @@ -20,31 +40,33 @@ def render(source: str, output_format: Literal["png", "svg"] = "png") -> bytes:

filename = f"tmp_mermaid.{output_format}"

if os.name == "nt":
executable = "mmdc.cmd"
else:
executable = "mmdc"
cmd = [
get_mmdc(),
"--input",
"-",
"--output",
filename,
"--outputFormat",
output_format,
]
if is_docker():
cmd.extend(
["-p", os.path.join(os.path.dirname(__file__), "puppeteer-config.json")]
)
LOGGER.debug(f"Executing: {' '.join(cmd)}")
try:
cmd = [
executable,
"--input",
"-",
"--output",
filename,
"--outputFormat",
output_format,
]
proc = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
text=False,
)
proc.communicate(input=source.encode("utf-8"))
stdout, stderr = proc.communicate(input=source.encode("utf-8"))
if proc.returncode:
raise RuntimeError(
f"failed to convert Mermaid diagram; exit code: {proc.returncode}"
f"failed to convert Mermaid diagram; exit code: {proc.returncode}, "
f"output:\n{stdout.decode('utf-8')}\n{stderr.decode('utf-8')}"
)
with open(filename, "rb") as image:
return image.read()
Expand Down
8 changes: 8 additions & 0 deletions md2conf/puppeteer-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"executablePath": "/usr/bin/chromium-browser",
"args": [
"--no-sandbox",
"--disable-gpu",
"--disable-setuid-sandbox"
]
}
8 changes: 7 additions & 1 deletion package.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
set -e
#
# Builds a Python package and runs unit tests in Docker
#

PYTHON=python3

Expand All @@ -9,11 +12,14 @@ if [ -d *.egg-info ]; then rm -rf *.egg-info; fi
# create PyPI package for distribution
$PYTHON -m build

docker build -f Dockerfile -t md2conf-image .
docker run -i -t --rm --env-file .env --name md2conf -v $(pwd):/data md2conf-image sample/index.md --ignore-invalid-url

# test PyPI package with various Python versions
# pass environment variables from the file `.env`
for PYTHON_VERSION in 3.8 3.9 3.10 3.11 3.12
do
docker build -f test.dockerfile -t py-$PYTHON_VERSION-image --build-arg PYTHON_VERSION=$PYTHON_VERSION .
docker run -it --env-file .env --rm py-$PYTHON_VERSION-image python3 -m unittest discover tests
docker run -i -t --rm --env-file .env py-$PYTHON_VERSION-image python3 -m unittest discover tests
docker rmi py-$PYTHON_VERSION-image
done
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ exclude =
[options.package_data]
md2conf =
entities.dtd
puppeteer-config.json
py.typed

[options.entry_points]
Expand Down
31 changes: 25 additions & 6 deletions test.dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
ARG PYTHON_VERSION=3.9
FROM python:${PYTHON_VERSION}-alpine
RUN PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --upgrade pip

FROM python:${PYTHON_VERSION}-alpine as host

# set environment for @mermaid-js/mermaid-cli
# https://github.com/mermaid-js/mermaid-cli/blob/master/Dockerfile
ENV CHROME_BIN="/usr/bin/chromium-browser" \
PUPPETEER_SKIP_DOWNLOAD="true"

# install dependencies for @mermaid-js/mermaid-cli
# https://github.com/mermaid-js/mermaid-cli/blob/master/install-dependencies.sh
RUN apk add chromium font-noto-cjk font-noto-emoji terminus-font ttf-dejavu ttf-freefont ttf-font-awesome ttf-inconsolata ttf-linux-libertine \
&& fc-cache -f

RUN apk add --update nodejs npm
RUN addgroup md2conf && adduser -D -G md2conf md2conf
USER md2conf
WORKDIR /home/md2conf
RUN npm install @mermaid-js/mermaid-cli

FROM host as runner

COPY dist/*.whl dist/
RUN python3 -m pip install `ls -1 dist/*.whl`
COPY sample/ sample/
COPY tests/*.py tests/
COPY tests/source/*.md tests/source/
COPY tests/target/*.xml tests/target/
COPY --chown=md2conf:md2conf sample/ sample/
COPY --chown=md2conf:md2conf tests/*.py tests/
COPY --chown=md2conf:md2conf tests/source/*.md tests/source/
COPY --chown=md2conf:md2conf tests/target/*.xml tests/target/

0 comments on commit e2b6389

Please sign in to comment.