├── .github
├── CODEOWNERS
├── FUNDING.yml
├── dependabot.yaml
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ ├── dockerhub.yaml
│ ├── publish.yaml
│ ├── linter.yaml
│ ├── autoupdate-drawio-desktop.yaml
│ └── docker-drawio-desktop-headless.yaml
├── tests
├── expected
│ ├── output-create-command.log
│ ├── export-file1.log
│ ├── export-file2.log
│ ├── export-non-root.log
│ ├── export-check-firstrun.log
│ ├── export-check-secondrun.log
│ ├── export-check-thirdrun.log
│ ├── output-unknown-file.log
│ ├── export-issue-20.log
│ ├── fonts-chinese.png
│ ├── uniq-output-electron-security-warning.log
│ ├── uniq-output-unknown-file-electron-security-warning.log
│ ├── issue-20-frame-bug-dark.svg
│ └── issue-20-frame-bug-light.svg
├── fonts.bats
├── timeout.bats
├── error.bats
├── issues.bats
├── data
│ ├── issue-20
│ │ ├── frame-bug-dark.drawio
│ │ └── frame-bug-light.drawio
│ ├── fonts
│ │ └── chinese.drawio
│ ├── file 2.drawio
│ ├── file1.drawio
│ ├── file3.drawio
│ └── file4.drawio
├── export.bats
└── base.bats
├── src
├── unwanted-update-logs.txt
├── unwanted-security-warnings.txt
├── runner.sh
├── runner_wrapper.sh
└── entrypoint.sh
├── .gitignore
├── .editorconfig
├── SECURITY.md
├── LICENSE
├── DOCKER.md
├── CONTRIBUTING.md
├── Dockerfile
├── justfile
├── CODE_OF_CONDUCT.md
└── README.adoc
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @rlespinasse
2 |
--------------------------------------------------------------------------------
/tests/expected/output-create-command.log:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tests/expected/export-file1.log:
--------------------------------------------------------------------------------
1 | file1.drawio -> file1.pdf
2 |
--------------------------------------------------------------------------------
/tests/expected/export-file2.log:
--------------------------------------------------------------------------------
1 | file 2.drawio -> file 2.pdf
2 |
--------------------------------------------------------------------------------
/tests/expected/export-non-root.log:
--------------------------------------------------------------------------------
1 | file4.drawio -> file4.pdf
2 |
--------------------------------------------------------------------------------
/tests/expected/export-check-firstrun.log:
--------------------------------------------------------------------------------
1 | file3.drawio -> file3.pdf
2 |
--------------------------------------------------------------------------------
/tests/expected/export-check-secondrun.log:
--------------------------------------------------------------------------------
1 | file3.drawio -> file3-1.pdf
2 |
--------------------------------------------------------------------------------
/tests/expected/export-check-thirdrun.log:
--------------------------------------------------------------------------------
1 | file3.drawio -> file3.pdf
2 |
--------------------------------------------------------------------------------
/tests/expected/output-unknown-file.log:
--------------------------------------------------------------------------------
1 | Error: input file/directory not found
2 |
--------------------------------------------------------------------------------
/tests/expected/export-issue-20.log:
--------------------------------------------------------------------------------
1 | issue-20/frame-bug.drawio -> issue-20/frame-bug.svg
2 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: rlespinasse
4 |
--------------------------------------------------------------------------------
/src/unwanted-update-logs.txt:
--------------------------------------------------------------------------------
1 | Checking for beta autoupdate feature for deb/rpm distributions
2 | Found package-type: deb
3 |
--------------------------------------------------------------------------------
/tests/expected/fonts-chinese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rlespinasse/docker-drawio-desktop-headless/HEAD/tests/expected/fonts-chinese.png
--------------------------------------------------------------------------------
/src/unwanted-security-warnings.txt:
--------------------------------------------------------------------------------
1 | Failed to call
2 | Failed to connect
3 | Failed to post
4 | Floss manager service
5 | InitializeSandbox() called with
6 | dri3 extension not
7 |
--------------------------------------------------------------------------------
/src/runner.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euo pipefail
3 |
4 | if [[ "${SCRIPT_DEBUG_MODE:-false}" == "true" ]]; then
5 | set -x
6 | fi
7 |
8 | "${DRAWIO_DESKTOP_EXECUTABLE_PATH:?}" "$@" --no-sandbox --disable-gpu
9 |
--------------------------------------------------------------------------------
/tests/fonts.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | # shellcheck source=/dev/null
4 | . tests/base.bats
5 |
6 | @test "Fonts chinese" {
7 | docker_test "" 0 "export-fonts-chinese" "tests/data" -x -f png fonts/chinese.drawio
8 | diff tests/expected/fonts-chinese.png tests/data/fonts/chinese.png
9 | }
10 |
--------------------------------------------------------------------------------
/src/runner_wrapper.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euo pipefail
3 |
4 | if [[ "${SCRIPT_DEBUG_MODE:-false}" == "true" ]]; then
5 | set -x
6 | fi
7 |
8 | # Run and filter output
9 | "${DRAWIO_DESKTOP_RUNNER_COMMAND_LINE:?}" "$@" 2>&1 | grep -Fvf "${DRAWIO_DESKTOP_SOURCE_FOLDER:?}/unwanted-lines.txt"
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # node
2 | node_modules/
3 | package-lock.json
4 |
5 | # test runs
6 | output/
7 | *.pdf
8 | *.svg
9 | *.png
10 | !tests/expected/*.svg
11 | !tests/expected/*.png
12 |
13 | # non-root user runs
14 | home
15 | .cache
16 | .config
17 | core
18 |
19 | # repository
20 | patch.diff
21 | package.json
22 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # top-most EditorConfig file
2 | root = true
3 |
4 | # Unix-style newlines with a newline ending every file
5 | [*]
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 2
9 | end_of_line = lf
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 |
13 | [*.log]
14 | trim_trailing_whitespace = false
15 |
--------------------------------------------------------------------------------
/tests/timeout.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | # shellcheck source=/dev/null
4 | . tests/base.bats
5 |
6 | @test "Timeout for using create command" {
7 | docker_test "-e DRAWIO_DESKTOP_COMMAND_TIMEOUT=2s" 1 "output-create-command" "tests/data" --create
8 | }
9 |
10 | @test "Timeout for using wrong command" {
11 | docker_test "-e DRAWIO_DESKTOP_COMMAND_TIMEOUT=2s" 1 "output-wrong-command" "tests/data" --wrong-command
12 | }
13 |
--------------------------------------------------------------------------------
/tests/error.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | # shellcheck source=/dev/null
4 | . tests/base.bats
5 |
6 | @test "Output an error on unknown file" {
7 | docker_test "" 1 "output-unknown-file" "tests/data" -x unknown.drawio
8 | }
9 |
10 | @test "Output an error on unknown file with electron security warning" {
11 | docker_test "-e ELECTRON_DISABLE_SECURITY_WARNINGS=false" 0 "output-unknown-file-electron-security-warning" "tests/data" -x unknown.drawio
12 | }
13 |
--------------------------------------------------------------------------------
/.github/dependabot.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: 'docker'
4 | directory: '/'
5 | commit-message:
6 | prefix: 'feat: '
7 | schedule:
8 | interval: 'weekly'
9 | day: 'monday'
10 | time: '00:00'
11 | labels: []
12 |
13 | - package-ecosystem: 'github-actions'
14 | directory: '/'
15 | schedule:
16 | interval: 'weekly'
17 | groups:
18 | dependencies:
19 | patterns:
20 | - '*'
21 | labels: []
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior
15 |
16 | **Expected behavior**
17 | A clear and concise description of what you expected to happen.
18 |
19 | **Screenshots**
20 | If applicable, add screenshots to help explain your problem.
21 |
22 | **Additional context**
23 | Add any other context about the problem here.
24 |
--------------------------------------------------------------------------------
/tests/expected/uniq-output-electron-security-warning.log:
--------------------------------------------------------------------------------
1 | Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type:
2 | Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix")
3 | Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory
4 | Floss manager service not available, cannot set Floss enable/disable.
5 | InitializeSandbox() called with multiple threads in process gpu-process.
6 | dri3 extension not supported.
7 | file1.drawio -> file1.pdf
8 |
--------------------------------------------------------------------------------
/tests/expected/uniq-output-unknown-file-electron-security-warning.log:
--------------------------------------------------------------------------------
1 | Error: input file/directory not found
2 | Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type:
3 | Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix")
4 | Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory
5 | Floss manager service not available, cannot set Floss enable/disable.
6 | InitializeSandbox() called with multiple threads in process gpu-process.
7 | dri3 extension not supported.
8 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/tests/issues.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | # shellcheck source=/dev/null
4 | . tests/base.bats
5 |
6 | @test "Issue 20 : frame bug / svg :: theme=light" {
7 | docker_test "" 0 "export-issue-20-light" "tests/data" -x -f svg issue-20/frame-bug-light.drawio --svg-theme light
8 | diff <(xmllint --format tests/expected/issue-20-frame-bug-light.svg) <(xmllint --format tests/data/issue-20/frame-bug-light.svg)
9 | }
10 |
11 | @test "Issue 20 : frame bug / svg :: theme=dark" {
12 | docker_test "" 0 "export-issue-20-dark" "tests/data" -x -f svg issue-20/frame-bug-dark.drawio --svg-theme dark
13 | diff <(xmllint --format tests/expected/issue-20-frame-bug-dark.svg) <(xmllint --format tests/data/issue-20/frame-bug-dark.svg)
14 | }
15 |
--------------------------------------------------------------------------------
/.github/workflows/dockerhub.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Update Docker Hub information
3 |
4 | on:
5 | release:
6 | types: [published]
7 | push:
8 | branches:
9 | - v1.x
10 | paths:
11 | - DOCKER.md
12 | - .github/workflows/dockerhub.yaml
13 |
14 | permissions: read-all
15 |
16 | jobs:
17 | dockerHubDescription:
18 | runs-on: ubuntu-latest
19 |
20 | steps:
21 | - uses: actions/checkout@v6
22 |
23 | - name: Sync information on Docker Hub
24 | uses: peter-evans/dockerhub-description@v5
25 | with:
26 | username: rlespinasse
27 | password: ${{ secrets.DOCKER_PASSWORD }}
28 | repository: rlespinasse/drawio-desktop-headless
29 | readme-filepath: ./DOCKER.md
30 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions and Branches
4 |
5 | | Version | Supported | End of Support | Branch |
6 | | ------- | ------------------ | -------------- | ------ |
7 | | 1.x | :white_check_mark: | | v1.x |
8 |
9 | ### End of Life of a branch
10 |
11 | Since `2024-10-27`, when a new major version is released,
12 |
13 | - The previous one will continue to receive security patches for 3 months,
14 | - After the 3 months, the branch is deleted, and only the tags remain.
15 |
16 | ## Reporting a Vulnerability
17 |
18 | In this project, you can report a Vulnerability by creating a [draft security advisory](https://github.com/rlespinasse/docker-drawio-desktop-headless/security/advisories).
19 |
20 | If the vulnerability is confirmed, a fix will be produced and the advisory will be published.
21 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Publish to Registry
3 |
4 | on:
5 | release:
6 | types: [published]
7 |
8 | permissions: read-all
9 |
10 | jobs:
11 | update:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v6
15 |
16 | - uses: rlespinasse/github-slug-action@v5
17 |
18 | - name: Set up QEMU
19 | uses: docker/setup-qemu-action@v3
20 | with:
21 | platforms: "arm64,arm"
22 |
23 | - name: Set up Docker Buildx
24 | uses: docker/setup-buildx-action@v3
25 |
26 | - name: Publish to Registry
27 | uses: elgohr/Publish-Docker-Github-Action@v5
28 | with:
29 | name: rlespinasse/drawio-desktop-headless
30 | username: ${{ secrets.DOCKER_USERNAME }}
31 | password: ${{ secrets.DOCKER_PASSWORD }}
32 | tags: "latest,${{ env.GITHUB_REF_SLUG }}"
33 | platforms: linux/amd64,linux/arm64
34 |
--------------------------------------------------------------------------------
/tests/data/issue-20/frame-bug-dark.drawio:
--------------------------------------------------------------------------------
1 | xZTbToQwEIafhstNoAi7XrpHo9GYrMbVG1NpOWhhsFsEfHrLthwqJsbEww2ZfjP8AzM/WO4irTYc5/EFEMosZJPKcpcWQlPfldcG1Ap4s5kCEU+IQk4Ptskb1dDWtEgI3RuFAoCJJDdhAFlGA2EwzDmUZlkIzOya44iOwDbAbExvEyJiRdHM7vkpTaJYd3aRTjzi4DniUGS6XQYZVZkUtyq6dB9jAuUAuSvLXXAAoaK0WlDWDLUd2PHT9f38YbfFDK+L25V9tirZRImtv3NL926cZuJnpdGx0n7FrNCTtJDPZJf5owyiJmhBCLK7HIOo9dD9lwLaxGR/sMSJLHBQXvXJVmUDQDpp/lFbPraSH+HBYyCjO5L7yJuwSNma41SG8zJOBN3mOGh4KY0uWSxSJk9Ok9bO8LyGt3bw7U79yxHrVbxSLmg1cJ4e+YZCSgWvZYnOHmnz1Oax7D3qewrFA3t2nxXWn0XUCfcbloFe8ucLd+0wu6zvyvPl1d1ucrPxQrLTHvmDfc8x+Z/lHtZpLjdMGFsAAy4BoSEuDv33gsMzHfPfsoLjm15wnLEZpvbYDNPve0Ee+//SITf467urdw==
--------------------------------------------------------------------------------
/tests/data/issue-20/frame-bug-light.drawio:
--------------------------------------------------------------------------------
1 | xZTbToQwEIafhstNoAi7XrpHo9GYrMbVG1NpOWhhsFsEfHrLthwqJsbEww2ZfjP8AzM/WO4irTYc5/EFEMosZJPKcpcWQlPfldcG1Ap4s5kCEU+IQk4Ptskb1dDWtEgI3RuFAoCJJDdhAFlGA2EwzDmUZlkIzOya44iOwDbAbExvEyJiRdHM7vkpTaJYd3aRTjzi4DniUGS6XQYZVZkUtyq6dB9jAuUAuSvLXXAAoaK0WlDWDLUd2PHT9f38YbfFDK+L25V9tirZRImtv3NL926cZuJnpdGx0n7FrNCTtJDPZJf5owyiJmhBCLK7HIOo9dD9lwLaxGR/sMSJLHBQXvXJVmUDQDpp/lFbPraSH+HBYyCjO5L7yJuwSNma41SG8zJOBN3mOGh4KY0uWSxSJk9Ok9bO8LyGt3bw7U79yxHrVbxSLmg1cJ4e+YZCSgWvZYnOHmnz1Oax7D3qewrFA3t2nxXWn0XUCfcbloFe8ucLd+0wu6zvyvPl1d1ucrPxQrLTHvmDfc8x+Z/lHtZpLjdMGFsAAy4BoSEuDv33gsMzHfPfsoLjm15wnLEZpvbYDNPve0Ee+//SITf467urdw==
--------------------------------------------------------------------------------
/.github/workflows/linter.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Lint Code Base
3 |
4 | on: pull_request
5 |
6 | permissions: read-all
7 |
8 | jobs:
9 | lint:
10 | runs-on: ubuntu-latest
11 |
12 | permissions:
13 | contents: read
14 | packages: read
15 | statuses: write
16 |
17 | steps:
18 | - name: Checkout Code
19 | uses: actions/checkout@v6
20 | with:
21 | # Full git history is needed to get a proper
22 | # list of changed files within `super-linter`
23 | fetch-depth: 0
24 |
25 | - name: Lint Code Base
26 | uses: super-linter/super-linter@v8
27 | env:
28 | VALIDATE_ALL_CODEBASE: false
29 | VALIDATE_BIOME_FORMAT: false
30 | VALIDATE_BIOME_LINT: false
31 | VALIDATE_GITHUB_ACTIONS_ZIZMOR: false
32 | VALIDATE_TRIVY: false
33 | VALIDATE_YAML_PRETTIER: false
34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35 |
--------------------------------------------------------------------------------
/.github/workflows/autoupdate-drawio-desktop.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Autoupdate Drawio Desktop
3 |
4 | on:
5 | schedule:
6 | - cron: "0 0 * * 1" # Every Monday at midnight (UTC)
7 | workflow_dispatch:
8 |
9 | permissions:
10 | contents: write
11 | pull-requests: write
12 |
13 | concurrency:
14 | group: autoupdate-drawio-desktop
15 | cancel-in-progress: true
16 |
17 | jobs:
18 | autoupdate:
19 | runs-on: ubuntu-latest
20 |
21 | steps:
22 | - uses: actions/checkout@v6
23 |
24 | - uses: taiki-e/install-action@just
25 |
26 | - run: just autoupdate-drawio-desktop
27 | id: autoupdate-drawio-desktop
28 | env:
29 | GH_TOKEN: ${{ secrets.GH_TOKEN }}
30 | shell: bash
31 |
32 | - uses: peter-evans/create-pull-request@v7
33 | with:
34 | title: "feat: update to drawio-desktop ${{ steps.autoupdate-drawio-desktop.outputs.release_version }}"
35 | branch: autoupdate-drawio-desktop
36 | token: ${{ secrets.GH_TOKEN }}
37 |
--------------------------------------------------------------------------------
/src/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euo pipefail
3 |
4 | if [[ "${SCRIPT_DEBUG_MODE:-false}" == "true" ]]; then
5 | set -x
6 | fi
7 |
8 | # Prepare output cleaning
9 | touch "${DRAWIO_DESKTOP_SOURCE_FOLDER:?}/unwanted-lines.txt"
10 | if [[ "${ELECTRON_DISABLE_SECURITY_WARNINGS:?}" == "true" ]]; then
11 | cat "${DRAWIO_DESKTOP_SOURCE_FOLDER:?}/unwanted-security-warnings.txt" >>"${DRAWIO_DESKTOP_SOURCE_FOLDER:?}/unwanted-lines.txt"
12 | fi
13 |
14 | if [[ "${DRAWIO_DISABLE_UPDATE:?}" == "true" ]]; then
15 | # Remove 'deb support' logs
16 | # since 'autoUpdater.logger.transports.file.level' is set as 'info' on drawio-desktop
17 | cat "${DRAWIO_DESKTOP_SOURCE_FOLDER:?}/unwanted-update-logs.txt" >>"${DRAWIO_DESKTOP_SOURCE_FOLDER:?}/unwanted-lines.txt"
18 | fi
19 |
20 | # Start Xvfb
21 | export DISPLAY="${XVFB_DISPLAY:?}"
22 | # shellcheck disable=SC2086
23 | # shellcheck disable=SC2154
24 | Xvfb "${XVFB_DISPLAY:?}" ${XVFB_OPTIONS} &
25 |
26 | # Run
27 |
28 | timeout "${DRAWIO_DESKTOP_COMMAND_TIMEOUT:?}" "${DRAWIO_DESKTOP_SOURCE_FOLDER:?}/runner_wrapper.sh" "$@"
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Romain Lespinasse
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/tests/export.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | # shellcheck source=/dev/null
4 | . tests/base.bats
5 |
6 | @test "Export a drawio file as pdf" {
7 | docker_test "" 0 "export-file1" "tests/data" -x file1.drawio
8 | }
9 |
10 | @test "Export a drawio file as pdf with electron security warning" {
11 | docker_test "-e ELECTRON_DISABLE_SECURITY_WARNINGS=false" 0 "output-electron-security-warning" "tests/data" -x file1.drawio
12 | }
13 |
14 | @test "Export a drawio file with space in its name" {
15 | docker_test "" 0 "export-file2" "tests/data" -x "file 2.drawio"
16 | }
17 |
18 | @test "Export as non-root" {
19 | docker_test "--user $(id --user):$(id --group) -v /etc/passwd:/etc/passwd --env HOME=/data/home" 0 "export-non-root" "tests/data" -x file4.drawio
20 | }
21 |
22 | @test "Export using unknown argument" {
23 | docker_test "" 0 "export-file1" "tests/data" --export file1.drawio --wrong-argument
24 | }
25 |
26 | @test "Export with check command" {
27 | docker_test "" 1 "export-check-firstrun" "tests/data" -export --check file3.drawio
28 | docker_test "" 1 "export-check-secondrun" "tests/data" -export --check file3.drawio
29 | docker_test "" 1 "export-check-thirdrun" "tests/data" -export file3.drawio
30 | }
31 |
--------------------------------------------------------------------------------
/DOCKER.md:
--------------------------------------------------------------------------------
1 | # Draw.io Desktop Headless docker image
2 |
3 | [Dockerized headless][1] version of [Draw.io Desktop][2]
4 |
5 | ## What is does
6 |
7 | Draw.io Desktop expose a command-line client to allow us to create, check or export diagrams.
8 |
9 | Since Draw.io Desktop is an GUI application, we need an GUI environment to run it.
10 | And this prevent us to use it for automation in non-GUI environment such as CI tools.
11 |
12 | This [docker image][1] enable us to run the command-line client in a headless mode.
13 |
14 | ## Running
15 |
16 | ```bash
17 | docker run -it -v $(pwd):/data rlespinasse/drawio-desktop-headless
18 | ```
19 |
20 | Read about [docker image configuration][3]
21 |
22 | ## License
23 |
24 | View [license information][4] for the software contained in this image.
25 |
26 | As for any pre-built image usage, it is the image user's responsibility to ensure that any use of this image complies with any relevant licenses for all software contained within.
27 |
28 | [1]: https://github.com/rlespinasse/docker-drawio-desktop-headless
29 | [2]: https://github.com/jgraph/drawio-desktop
30 | [3]: https://github.com/rlespinasse/docker-drawio-desktop-headless/blob/v1.x/README.adoc#configuration
31 | [4]: https://github.com/rlespinasse/docker-drawio-desktop-headless/blob/v1.x/LICENSE
32 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute to Docker Draw.io Desktop Headless
2 |
3 | ## Did you find a bug
4 |
5 | * **Do not open up a GitHub issue if the bug is a security vulnerability**, and instead to refer to our [security policy][1].
6 |
7 | * **Ensure the bug was not already reported** by searching on GitHub under [Issues][2].
8 |
9 | * If you're unable to find an open issue addressing the problem, [open a 'Bug' issue][4].
10 | Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring.
11 |
12 | ## Did you write a patch that fixes a bug
13 |
14 | * Open a new GitHub pull request with the patch.
15 |
16 | * Ensure the PR description clearly describes the problem and solution.
17 | Include the relevant issue number if applicable.
18 |
19 | ## Do you intend to add a new feature or change an existing one
20 |
21 | * Suggest your change by [opening a 'Feature request' issue][5]
22 |
23 | ## Do you have questions about the source code
24 |
25 | * [open an issue][3] with your question.
26 |
27 | Thanks!
28 |
29 | [1]: https://github.com/rlespinasse/docker-drawio-desktop-headless/security/policy
30 | [2]: https://github.com/rlespinasse/docker-drawio-desktop-headless/issues
31 | [3]: https://github.com/rlespinasse/docker-drawio-desktop-headless/issues/new
32 | [4]: https://github.com/rlespinasse/docker-drawio-desktop-headless/issues/new?assignees=&labels=bug&template=bug_report.md&title=
33 | [5]: https://github.com/rlespinasse/docker-drawio-desktop-headless/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=
--------------------------------------------------------------------------------
/tests/base.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | docker_test() {
4 | # Get parameters
5 | local docker_opts=$1
6 | local status=$2
7 | local output_file=$3
8 | local data_folder=$4
9 | shift
10 | shift
11 | shift
12 | shift
13 |
14 | # Run command
15 | # shellcheck disable=SC2086
16 | echo docker container run -t $docker_opts -w /data -v "$(pwd)/${data_folder:-}":/data ${DOCKER_IMAGE} "$@" >>tests/output/$output_file-command.log
17 | # shellcheck disable=SC2086
18 | run docker container run -t $docker_opts -w /data -v "$(pwd)/${data_folder:-}":/data ${DOCKER_IMAGE} "$@"
19 |
20 | # Remove timed logging tags on electron logs by default.
21 | # shellcheck disable=SC2154
22 | echo "$output" | tee "tests/output/$output_file.log" | sed 's#\[.*:.*/.*\..*:.*:.*\(.*\)\] ##' >"tests/output/$output_file-comp.log"
23 |
24 | # Test status
25 | # shellcheck disable=SC2086
26 | [ "$status" -eq $status ]
27 | # Test output
28 | if [ -f "tests/expected/$output_file.log" ]; then
29 | diff -u --strip-trailing-cr "tests/expected/$output_file.log" "tests/output/$output_file-comp.log" >"tests/output/$output_file-diff.log"
30 | elif [ -f "tests/expected/uniq-$output_file.log" ]; then
31 | # For now, I remove sqlite_persistent_shared_dictionary_store logs from expected output since this line is inconsistent across runs
32 | diff -u --strip-trailing-cr "tests/expected/uniq-$output_file.log" <(LC_COLLATE=C sort -u "tests/output/$output_file-comp.log" | grep -v "sqlite_persistent_shared_dictionary_store") >"tests/output/$output_file-diff.log"
33 | fi
34 | if [ -f "tests/output/$output_file-diff.log" ]; then
35 | [ "$(cat "tests/output/$output_file-diff.log")" = "" ]
36 | fi
37 | }
38 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | #checkov:skip=CKV_DOCKER_2
2 | #checkov:skip=CKV_DOCKER_3
3 | FROM debian:trixie
4 | ARG TARGETARCH
5 |
6 | WORKDIR "/opt/drawio-desktop"
7 |
8 | # hadolint ignore=DL3008,DL3015
9 | RUN <
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/tests/data/file 2.drawio:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/tests/data/file1.drawio:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/tests/data/file3.drawio:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/tests/data/file4.drawio:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/justfile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env -S just --justfile
2 |
3 | set quiet := true
4 |
5 | # Set default architecture based on machine type
6 | arch := if arch() == "aarch64" { "arm64" } else { "amd64" }
7 |
8 | # Default docker image name
9 | docker_image := env_var_or_default("DOCKER_IMAGE", "rlespinasse/drawio-desktop-headless:local")
10 |
11 | default:
12 | just --choose
13 |
14 | # Build the Docker image for current architecture
15 | [group('Development mode')]
16 | build:
17 | docker build --build-arg="TARGETARCH={{arch}}" -t {{docker_image}} .
18 |
19 | # Build the Docker image without cache
20 | [group('Development mode')]
21 | build-no-cache:
22 | docker build --build-arg="TARGETARCH={{arch}}" --no-cache --progress plain -t {{docker_image}} .
23 |
24 | # Build for multiple architectures
25 | [group('Development mode')]
26 | build-multiarch:
27 | docker buildx build --platform linux/amd64,linux/arm64 -t {{docker_image}} .
28 |
29 | # Clean up test artifacts
30 | [group('Development mode')]
31 | cleanup:
32 | rm -rf tests/output
33 | rm -rf tests/data/home
34 | find tests/data \( -name "*.pdf" -o -name "*.svg" -o -name "*.png" \) -delete
35 |
36 | # Run the Docker container
37 | [group('Development mode')]
38 | run *ARGS:
39 | docker run -t {{env_var_or_default("DOCKER_OPTIONS", "")}} -w /data -v {{invocation_directory()}}:/data {{docker_image}} {{ARGS}}
40 |
41 | # Run tests
42 | [group('Testing mode')]
43 | test: cleanup build test-ci
44 |
45 | # Setup CI test environment
46 | [group('Testing mode')]
47 | test-ci-setup:
48 | npm install bats
49 | sudo apt-get update
50 | sudo apt-get install -y libxml2-utils
51 |
52 | # Run CI tests
53 | [group('Testing mode')]
54 | test-ci:
55 | mkdir -p tests/output
56 | DOCKER_IMAGE={{docker_image}} npx bats --verbose-run -r tests
57 |
58 | # Auto-update drawio-desktop version
59 | [group('Maintenance mode')]
60 | autoupdate-drawio-desktop:
61 | #!/usr/bin/env bash
62 | DRAWIO_DESKTOP_RELEASE=$(gh release list --repo jgraph/drawio-desktop | grep "Latest" | cut -f1)
63 | sed -i 's/DRAWIO_VERSION=.*/DRAWIO_VERSION="'$DRAWIO_DESKTOP_RELEASE'"/' Dockerfile
64 | sed -i 's/Draw\.io Desktop v.*/Draw.io Desktop v'$DRAWIO_DESKTOP_RELEASE'\]/' README.adoc
65 | if [ -n "${GITHUB_OUTPUT}" ]; then
66 | echo "release_version=$DRAWIO_DESKTOP_RELEASE" >> "${GITHUB_OUTPUT}"
67 | fi
68 | echo "Updated to Draw.io Desktop version $DRAWIO_DESKTOP_RELEASE"
69 |
70 | [group('Maintenance mode')]
71 | patch: patch-unwanted-security-warnings patch-tests
72 |
73 | [private]
74 | patch-unwanted-security-warnings:
75 | #!/usr/bin/env bash
76 | cat tests/output/output-electron-security-warning-comp.log | \
77 | # For now, I remove sqlite_persistent_shared_dictionary_store logs from expected output since this line is inconsistent across runs
78 | grep -v "sqlite_persistent_shared_dictionary_store" | \
79 | LC_COLLATE=C sort -u > tests/expected/uniq-output-electron-security-warning.log
80 | cat tests/output/output-unknown-file-electron-security-warning-comp.log | \
81 | # For now, I remove sqlite_persistent_shared_dictionary_store logs from expected output since this line is inconsistent across runs
82 | grep -v "sqlite_persistent_shared_dictionary_store" | \
83 | LC_COLLATE=C sort -u > tests/expected/uniq-output-unknown-file-electron-security-warning.log
84 |
85 | echo
86 | {
87 | awk '{print $1, $2, $3}' tests/output/output-electron-security-warning-comp.log;
88 | awk '{print $1, $2, $3}' tests/output/output-unknown-file-electron-security-warning-comp.log;
89 | } | \
90 | grep -v "file1.drawio" | \
91 | grep -v "input file/directory" | \
92 | LC_COLLATE=C sort -u > src/unwanted-security-warnings.txt
93 | git diff --exit-code src/unwanted-security-warnings.txt || \
94 | echo "Unwanted Security Warnings have been updated. Please check the changes before committing."
95 | git diff --exit-code tests/expected/uniq-* || \
96 | echo "Test files have been updated. Please check the changes before committing."
97 |
98 | [private]
99 | patch-tests:
100 | #!/usr/bin/env bash
101 | mv tests/data/issue-20/frame-bug-dark.svg tests/expected/issue-20-frame-bug-dark.svg
102 | mv tests/data/issue-20/frame-bug-light.svg tests/expected/issue-20-frame-bug-light.svg
103 | mv tests/data/fonts/chinese.png tests/expected/fonts-chinese.png
104 | git diff --exit-code tests/expected || \
105 | echo "Test files have been updated. Please check the changes before committing."
106 |
--------------------------------------------------------------------------------
/.github/workflows/docker-drawio-desktop-headless.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Build And Release
3 |
4 | on:
5 | pull_request:
6 | push:
7 | branches:
8 | - v1.x
9 |
10 | permissions:
11 | contents: read # Default to 'read' for security
12 | pull-requests: read
13 | id-token: write # Added for potential OIDC in release job (packages/registry login)
14 |
15 | jobs:
16 | build:
17 | runs-on: ubuntu-latest
18 |
19 | permissions:
20 | contents: write # For stefanzweifel/git-auto-commit-action
21 | pull-requests: write # For peter-evans/create-or-update-comment
22 |
23 | concurrency:
24 | group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
25 | cancel-in-progress: true
26 |
27 | steps:
28 | - name: Checkout Source Branch
29 | uses: actions/checkout@v6
30 | with:
31 | fetch-depth: 0
32 | ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }}
33 | token: ${{ secrets.GH_TOKEN }}
34 |
35 | - uses: rlespinasse/github-slug-action@v5
36 |
37 | - uses: taiki-e/install-action@v2
38 | with:
39 | tool: just
40 |
41 | - name: Build Docker Image
42 | run: just build
43 | env:
44 | DOCKER_IMAGE: ${{ github.repository }}:${{ env.GITHUB_REF_SLUG }}
45 |
46 | - name: Setup CI for test
47 | run: just test-ci-setup
48 |
49 | - name: Test Docker Image
50 | id: test_ci
51 | run: just test-ci
52 | env:
53 | DOCKER_IMAGE: ${{ github.repository }}:${{ env.GITHUB_REF_SLUG }}
54 | continue-on-error: true
55 |
56 | - name: Store Output Logs & Files
57 | if: steps.test_ci.outcome == 'failure'
58 | uses: actions/upload-artifact@v5
59 | with:
60 | name: test-artifacts
61 | path: |
62 | tests/output/*.log
63 | tests/data
64 | !tests/data/*.drawio
65 | !tests/data/*/*.drawio
66 |
67 | - name: Patch Code (if Test Failed)
68 | if: steps.test_ci.outcome == 'failure'
69 | run: just patch
70 |
71 | - name: Generate Patch Diff
72 | if: steps.test_ci.outcome == 'failure'
73 | id: patch_diff_step
74 | run: |
75 | git diff HEAD^ HEAD > patch.diff
76 | # Set output to be used by the comment action
77 | {
78 | echo "diff<> "$GITHUB_OUTPUT"
82 |
83 | - name: Comment Patch Diff on PR
84 | uses: peter-evans/create-or-update-comment@v5
85 | if: steps.test_ci.outcome == 'failure' && github.event_name == 'pull_request' && steps.patch_diff_step.outputs.diff != ''
86 | with:
87 | issue-number: ${{ github.event.pull_request.number }}
88 | body: |
89 | :warning: A patch has been applied following the tests failure.
90 |
91 |
92 | Display patch content
93 |
94 | ```diff
95 | ${{ steps.patch_diff_step.outputs.diff }}
96 | ```
97 |
98 | continue-on-error: true
99 |
100 | - name: Commit and Push Patch (if needed)
101 | uses: stefanzweifel/git-auto-commit-action@v7
102 | if: steps.test_ci.outcome == 'failure'
103 | with:
104 | commit_message: "fix: apply automated patch after tests failure"
105 | branch: ${{ github.head_ref }}
106 |
107 | build-multiarch:
108 | runs-on: ubuntu-latest
109 |
110 | concurrency:
111 | group: ${{ github.workflow }}-${{ github.ref }}-multiarch-${{ github.event_name }}
112 | cancel-in-progress: true
113 |
114 | steps:
115 | - uses: actions/checkout@v6
116 |
117 | - uses: rlespinasse/github-slug-action@v5
118 |
119 | - name: Set up QEMU
120 | uses: docker/setup-qemu-action@v3
121 | with:
122 | platforms: "arm64,arm"
123 |
124 | - name: Set up Docker Buildx
125 | uses: docker/setup-buildx-action@v3
126 |
127 | - name: Cache Docker layers
128 | uses: actions/cache@v4
129 | with:
130 | path: /tmp/.buildx-cache
131 | key: ${{ runner.os }}-buildx-${{ github.sha }}
132 | restore-keys: |
133 | ${{ runner.os }}-buildx-
134 |
135 | - uses: taiki-e/install-action@v2
136 | with:
137 | tool: just
138 |
139 | - name: Build Docker Image
140 | run: just build-multiarch
141 | env:
142 | DOCKER_IMAGE: ${{ github.repository }}:${{ env.GITHUB_REF_SLUG }}
143 |
144 | release:
145 | runs-on: ubuntu-latest
146 |
147 | permissions:
148 | contents: write # Required for releases
149 | packages: write # Required to push packages/images to GHCR
150 | issues: write # If release-that creates issues
151 |
152 | needs:
153 | - build
154 | - build-multiarch
155 |
156 | # Concurrency is good here, but cancellation should be disabled so a push
157 | # doesn't cancel a running release.
158 | concurrency:
159 | group: ${{ github.workflow }}-${{ github.ref }}-release
160 | cancel-in-progress: false
161 |
162 | steps:
163 | - uses: actions/checkout@v6
164 |
165 | - name: Release this docker image
166 | uses: rlespinasse/release-that@v1
167 | with:
168 | github-token: ${{ secrets.GH_TOKEN }}
169 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, caste, color, religion, or sexual
10 | identity and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the overall
26 | community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or advances of
31 | any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email address,
35 | without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official email address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | .
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series of
86 | actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or permanent
93 | ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within the
113 | community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.1, available at
119 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
120 |
121 | Community Impact Guidelines were inspired by
122 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
123 |
124 | For answers to common questions about this code of conduct, see the FAQ at
125 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
126 | [https://www.contributor-covenant.org/translations][translations].
127 |
128 | [homepage]: https://www.contributor-covenant.org
129 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
130 | [Mozilla CoC]: https://github.com/mozilla/diversity
131 | [FAQ]: https://www.contributor-covenant.org/faq
132 | [translations]: https://www.contributor-covenant.org/translations
133 |
--------------------------------------------------------------------------------
/README.adoc:
--------------------------------------------------------------------------------
1 | = Draw.io Desktop Headless docker image
2 |
3 | Dockerized headless version of https://github.com/jgraph/drawio-desktop[Draw.io Desktop v29.0.3]
4 |
5 | == What it does
6 |
7 | Draw.io Desktop exposes a command-line client to allow us to create, check or export diagrams.
8 |
9 | Since Draw.io Desktop is a GUI application, we need a GUI environment to run it.
10 | And this prevents us to use it for automation in non-GUI environments such as CI tools.
11 |
12 | This docker image enables us to run the command-line client in a headless mode by using a configurable **X** server.
13 |
14 | Other minor additions are available
15 |
16 | * Add timeout capability since the application can hang sometimes (due to user action needed in GUI mode)
17 | * Clear the output log from Electron Security Warning
18 | * Disable auto-update functionality to avoid unnecessary log
19 | * Multiple fonts from
20 | ** https://packages.debian.org/bullseye/fonts-liberation[fonts-liberation]
21 | ** https://packages.debian.org/bullseye/fonts-arphic-ukai[fonts-arphic-ukai]
22 | ** https://packages.debian.org/bullseye/fonts-arphic-uming[fonts-arphic-uming]
23 | ** https://packages.debian.org/bullseye/fonts-noto[fonts-noto]
24 | ** https://packages.debian.org/bullseye/fonts-noto-cjk[fonts-noto-cjk]
25 | ** https://packages.debian.org/bullseye/fonts-ipafont-mincho[fonts-ipafont-mincho]
26 | ** https://packages.debian.org/bullseye/fonts-ipafont-gothic[fonts-ipafont-gothic]
27 | ** https://packages.debian.org/bullseye/fonts-unfonts-core[fonts-unfonts-core]
28 |
29 | NOTE: Want a new font package, modify the `Dockerfile` to install the missing package.
30 |
31 | == Running
32 |
33 | .Default run
34 | [source,console]
35 | ----
36 | $ docker run -it -w /data -v $(pwd):/data rlespinasse/drawio-desktop-headless
37 | Usage: drawio [options] [input file/folder]
38 | ...
39 | ----
40 |
41 | .Run using non-root user
42 | [source,console]
43 | ----
44 | $ docker run -it \
45 | -u $(id -u):$(id -g) \ <1>
46 | -e HOME=/data/home -w /data \ <2>
47 | -v /etc/passwd:/etc/passwd \ <3>
48 | -v $(pwd):/data rlespinasse/drawio-desktop-headless
49 | Usage: drawio [options] [input file/folder]
50 | ...
51 | ----
52 | <1> Enable non-root user
53 | <2> env HOME need to contains the path of the working directory (can be the same)
54 | +
55 | .What if env HOME is not set properly?
56 | [%collapsible]
57 | ====
58 | [,console]
59 | ----
60 | Fontconfig error: No writable cache directories
61 | A JavaScript error occurred in the main process
62 | Uncaught Exception:
63 | Error: Failed to get 'userData' path
64 | at initDataListener (/opt/drawio/resources/app.asar/node_modules/electron-store/index.js:15:19)
65 | at new ElectronStore (/opt/drawio/resources/app.asar/node_modules/electron-store/index.js:48:32)
66 | at Object. (/opt/drawio/resources/app.asar/src/main/electron.js:15:15)
67 | at Module._compile (node:internal/modules/cjs/loader:1271:14)
68 | at Module._extensions..js (node:internal/modules/cjs/loader:1326:10)
69 | at Module.load (node:internal/modules/cjs/loader:1126:32)
70 | at Module._load (node:internal/modules/cjs/loader:967:12)
71 | at l._load (node:electron/js2c/asar_bundle:2:13642)
72 | at node:electron/js2c/browser_init:2:120247
73 | at node:electron/js2c/browser_init:2:120456
74 | /opt/drawio-desktop/runner.sh: line 4: 15 Trace/breakpoint trap (core dumped) "${DRAWIO_DESKTOP_EXECUTABLE_PATH:?}" "$@" --no-sandbox --disable-gpu
75 | ----
76 | ====
77 | <3> Needed to run drawio as non-root since v24.4.6
78 | +
79 | .What if this volume is not set properly?
80 | [%collapsible]
81 | ====
82 | [,console]
83 | ----
84 | A JavaScript error occurred in the main process
85 | Uncaught Exception:
86 | SystemError [ERR_SYSTEM_ERROR]: A system error occurred: uv_os_get_passwd returned ENOENT (no such file or directory)
87 | at new SystemError (node:internal/errors:259:5)
88 | at new NodeError (node:internal/errors:370:7)
89 | at Object.userInfo (node:os:365:11)
90 | at file:///opt/drawio/resources/app.asar/node_modules/atomically/dist/constants.js:10:29
91 | at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
92 | at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
93 | at async node:electron/js2c/browser_init:2:125628
94 | at async loadESM (node:internal/process/esm_loader:28:7)
95 | ----
96 | ====
97 |
98 | === Configuration
99 |
100 | [cols="2a,3a,1a",options="header"]
101 | |===
102 |
103 | | Environment Variable
104 | | Description
105 | | Default Value
106 |
107 | | **DRAWIO_DESKTOP_COMMAND_TIMEOUT**
108 | | To prevent Draw.io Desktop process to hang indefinitely.
109 |
110 | The value is a floating point number with an optional suffix: 's'
111 | for seconds (the default), 'm' for minutes, 'h' for hours or 'd'
112 | for days. A duration of 0 disables the associated timeout.
113 | | `10s`
114 |
115 | | **XVFB_DISPLAY**
116 | | Screen Display setup for XVFB
117 | | `:42`
118 |
119 | | **XVFB_OPTIONS**
120 | | Options for Xvfb
121 | | `-nolisten unix` (enable non-root run)
122 |
123 | | **ELECTRON_DISABLE_SECURITY_WARNINGS**
124 | | Avoid printing https://github.com/electron/electron/blob/master/docs/tutorial/security.md#electron-security-warnings[electron warning]
125 | | `true`
126 |
127 | | **DRAWIO_DISABLE_UPDATE**
128 | | Disable auto-update of Draw.io Desktop
129 | | `true`
130 |
131 | | **SCRIPT_DEBUG_MODE**
132 | | Enable `set -x` in internal scripts for debugging purpose
133 | | `false`
134 |
135 | |===
136 |
137 | == Use as docker base image
138 |
139 | This docker image can be used as the base image to build a higher-level tool upon it.
140 |
141 | In addition to running configuration, you have access to
142 |
143 | - `DRAWIO_DESKTOP_EXECUTABLE_PATH` to have access to the executable path of Draw.io Desktop.
144 | - `DRAWIO_DESKTOP_RUNNER_COMMAND_LINE` to run your script instead of the default one.
145 |
146 | === Used by
147 |
148 | * Docker image https://github.com/rlespinasse/drawio-export[**rlespinasse/drawio-export**] which enhance export capabilities of the **Draw.io Desktop Headless** docker image,
149 | ** And GitHub Action https://github.com/rlespinasse/drawio-export-action[**rlespinasse/drawio-export-action**] which is build on top of **drawio-export** docker image.
150 |
151 | == Thanks to
152 |
153 | Thanks for the community about https://github.com/jgraph/drawio-desktop/issues/127[the workaround docker-image based on Draw.io Desktop].
154 |
155 | == Contributing
156 |
157 | Pull requests are welcome.
158 | For major changes, please open an issue first to discuss what you would like to change.
159 |
160 | Please make sure to update tests as appropriate.
161 |
--------------------------------------------------------------------------------
/tests/expected/issue-20-frame-bug-dark.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/tests/expected/issue-20-frame-bug-light.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------