{"id":13565811,"url":"https://github.com/madhead/doktor","last_synced_at":"2025-08-30T16:36:47.704Z","repository":{"id":152765867,"uuid":"100120083","full_name":"madhead/doktor","owner":"madhead","description":"Jenkins plugin for automated documentation uploading to Confluence [Mirror]","archived":false,"fork":false,"pushed_at":"2019-04-10T22:52:33.000Z","size":8008,"stargazers_count":16,"open_issues_count":0,"forks_count":9,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-06-22T18:05:21.940Z","etag":null,"topics":["confluence","gradle","jenkins","jenkins-plugin","kotlin"],"latest_commit_sha":null,"homepage":"https://gitlab.com/madhead/doktor","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/madhead.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-08-12T15:14:40.000Z","updated_at":"2023-08-31T03:22:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"1bddf2f9-df07-4fcb-84fa-969dd884fdb6","html_url":"https://github.com/madhead/doktor","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/madhead/doktor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madhead%2Fdoktor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madhead%2Fdoktor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madhead%2Fdoktor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madhead%2Fdoktor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/madhead","download_url":"https://codeload.github.com/madhead/doktor/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madhead%2Fdoktor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272878211,"owners_count":25008340,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-30T02:00:09.474Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["confluence","gradle","jenkins","jenkins-plugin","kotlin"],"created_at":"2024-08-01T13:01:55.932Z","updated_at":"2025-08-30T16:36:47.688Z","avatar_url":"https://github.com/madhead.png","language":"Kotlin","funding_links":[],"categories":["Kotlin"],"sub_categories":[],"readme":"image:https://travis-ci.org/jenkinsci/doktor-plugin.svg?branch=master[\"Build Status\", link=\"https://travis-ci.org/jenkinsci/doktor-plugin\"]\nimage:https://codecov.io/gh/jenkinsci/doktor-plugin/branch/master/graph/badge.svg[\"Build Status\", link=\"https://codecov.io/gh/jenkinsci/doktor-plugin\"]\n\n= Doktor\n\nDoktor is a Jenkins plugin for automated documentation uploading to Confluence.\n\n== Usage\n\n=== Features\n\n==== Supported formats\n\nDoktor supports https://daringfireball.net/projects/markdown/syntax[Markdown] and http://asciidoc.org[AsciiDoc].\nMarkdown support is provided by awesome https://github.com/vsch/flexmark-java[flexmark-java] library.\nAsciiDoc is supported thanks to https://github.com/asciidoctor/asciidoctorj[AsciidoctorJ].\nPlease note that AsciiDoc support is very experimental.\n\n==== Front matter\n\n_Front matter_ is another word for _metadata_, used by bloggers and hipsters widely.\nDoktor uses front matter to configure the way pages appear in Confluence.\n\n===== Markdown\n\nDoktor supports http://www.yaml.org[YAML] front matter in your Markdown files.\nFront matter looks like a small YAML fragment at the beginning of the file, separated by a triple minus sign (`---`) in this case:\n\n[source,yml]\n----\n---\nkey: value\n---\n----\n\n===== AsciiDoc\n\nDoktor supports http://www.yaml.org[YAML] front matter in your AsciiDoc files as well.\nFront matter looks like a small YAML fragment at the beginning of the file, separated by a triple minus sign (`---`) in this case.\nNote, that due to a more strict YAML parser logic for AsciiDoc, strings with special characters need to be quoted:\n\n[source, asciidoc]\n----\n---\nkey: value\nkey_with_specials: 'value: with specials'\n---\n----\n\n===== Supported front matter attributes:\n\n`title`::\nRequired.\nPage title, unsurprisingly.\n\n`parent`::\nOptional.\nParent page title, if any.\nIf omitted, https://confluence.atlassian.com/doc/orphaned-pages-139542.html[\"orphaned\" page] will be created.\nIf parent page is not found by title, child page will not be created at all.\n\n`labels`::\nOptional.\nList of labels to add to a page.\n\n==== Tables\n\n===== Markdown\n\nThough Markdown does not have any support for tables, Doktor supports https://help.github.com/articles/organizing-information-with-tables[GitHub Flavored Markdown tables].\nYou can also create tables by inlining XHTML markup directly in your docs.\n\n===== AsciiDoc\n\nAsciiDoc (thus Asciidoctor and AsciidoctorJ) http://asciidoctor.org/docs/user-manual/#tables[supports tables natively].\n\n==== Images\n\nDoktor supports images.\nWhen an image is referred by relative URL it will be uploaded to a Confluence server as an attachment of a page, given unique name.\nWhen an image is referred by remote URL (Internet link) it will be referred by this URL from a Confluence server.\n\n===== Markdown\n\nhttps://daringfireball.net/projects/markdown/syntax#img[Markdown syntax] for images:\n\n[source, markdown]\n----\n![Millennium Falcon](./millennium_falcon.png \"The Millennium Falcon, Han Solo's most prized possession\")\n----\n\n===== AsciiDoc\n\nImages look like http://asciidoctor.org/docs/asciidoc-writers-guide/#images[this] is AsciiDoc:\n\n[source, asciidoc]\n----\n.The Millennium Falcon, Han Solo's most prized possession\n[link=http://starwars.wikia.com/wiki/Millennium_Falcon]\nimage::./millennium_falcon.png[Millennium Falcon,400,float=\"right\",align=\"center\"]\n----\n\nAs you see, AsciiDoc is more feature-rich.\n\n==== Diagrams\n\nDiagrams are only supported in AsciiDoc, the markup looks like this:\n\n[seqdiag]\n....\nseqdiag {\n  // normal edge and doted edge\n  A -\u003e B [label = \"normal edge\"];\n  B --\u003e C [label = \"dotted edge\"];\n\n  B \u003c-- C [label = \"return dotted edge\"];\n  A \u003c- B [label = \"return edge\"];\n\n  // asynchronus edge\n  A -\u003e\u003e B [label = \"asynchronus edge\"];\n  B --\u003e\u003e C [label = \"asynchronus dotted edge\"];\n\n  B \u003c\u003c-- C [label = \"return asynchronus doted edge\"];\n  A \u003c\u003c- B [label = \"return asynchronus edge\"];\n\n  // self referenced edge\n  A -\u003e A [label = \"self reference edge\"];\n}\n....\n\nThe snippet above will be rendered in this image:\n\nimage::https://github.com/madhead/doktor/blob/master/.github/images/seqdiag.png[]\n\nRead more about diagram syntax in http://asciidoctor.org/docs/asciidoctor-diagram[in the official AsciiDoc guide].\nBe warned, that most types of diagrams require external tools (like `seqdiag` or `dot`) to be installed and available on the `PATH`.\n\nCurrently, these diagrams are supported:\n\n - `actdiag` / `blockdiag` / `nwdiag` / `packetdiag` / `rackdiag` / `seqdiag`.\nThese diagrams require http://blockdiag.com[`blockdiag`] and related Python packages to be available on the `PATH`.\n - http://ditaa.sourceforge.net[`ditaa`].\nNo additional tools needed.\n - `graphviz`.\nObviously, requires http://www.graphviz.org[Graphviz] tool to be on the `PATH`.\n - `mermaid`\nRequires https://mermaidjs.github.io[mermaid] (version prior to `7.x`) and http://phantomjs.org[PhantomJS] to be on the `PATH`.\n - http://plantuml.com[`plantuml`]\nNo additional tools needed.\n\n==== Custom stylesheets\n\nConfluence allows space admins to provide custom stylesheets that override globals.\nDoktor supports styling generated content by wrapping it in a `\u003cdiv class=\"doktor\"\u003e`, so you can use `.doctor` prefix in your selector to stylize content.\n\n=== Configure Confluence servers\n\nAs you might suspect, Confluence REST API requires authentication.\nDoktor supports basic authentication (username and password).\nSo, first thing to do is to https://github.com/jenkinsci/credentials-plugin/blob/master/docs/user.adoc[configure credentials] in Jenkins.\n\nCreate a \"Username with password\" credentials to be used to authenticate on Confluence server:\n\nimage::https://github.com/madhead/doktor/blob/master/.github/images/new_credentials.png[]\n\nYou may have as many Confluence servers and credentials for them as you need.\n\nNext thing to do is to configure Confluence servers.\nGo to global configuration screen (\"Manage Jenkins\" -\u003e \"Configure System\") and find \"Confluence Servers\" section.\nConfigure the list of available Confluence servers:\n\nimage::https://github.com/madhead/doktor/blob/master/.github/images/confluence_servers.png[]\n\nNow, when you have some Confluence servers to publish documentation to, it's time test this plugin!\nYes, I'm using word \"test\" https://github.com/madhead/doktor/issues/new[intentionally] here.\n\n=== Pipeline step\n\nUsing Doktor with https://jenkins.io/doc/book/pipeline[pipelines] is very easy!\nHere is the full syntax of `doktor` step:\n\n[source,groovy]\n----\ndoktor\n\tserver : 'Cantina', // \u003c1\u003e\n\tmarkdownIncludePatterns: ['glob:**.md'], // \u003c2\u003e\n\tmarkdownExcludePatterns: ['glob:README.md'], // \u003c3\u003e\n\tasciidocIncludePatterns: ['glob:**.adoc', 'glob:**.asc'], // \u003c4\u003e\n\tasciidocExcludePatterns: ['glob:LICENSE.adoc', 'glob:CONTRIBUTING.asc'] // \u003c5\u003e\n----\n\u003c1\u003e One of the available Confluence servers\n\u003c2\u003e List of Java 8 https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-[PathMatcher specifications] for https://daringfireball.net/projects/markdown/syntax[Markdown] files to include.\n\u003c3\u003e List of Java 8 https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-[PathMatcher specifications] for https://daringfireball.net/projects/markdown/syntax[Markdown] files to exclude.\n\u003c4\u003e List of Java 8 https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-[PathMatcher specifications] for http://asciidoc.org[AsciiDoc] files to include.\n\u003c5\u003e List of Java 8 https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-[PathMatcher specifications] for http://asciidoc.org[AsciiDoc] files to exclude.\n\nYou can also try your luck with \"Snippet Generator\", available at `/pipeline-syntax` path of your Jenkins installation.\n\n=== Classic builds\n\nDoktor plays nice with \"classic\" builds too!\n\nimage::https://github.com/madhead/doktor/blob/master/.github/images/freestyle_config.png[]\n\nClick those question icons on the right if you need any help.\n\n== Limitations\n\nDoktor recreates pages instead of updating them.\nRecreating pages has some counterintuitive effects:\n\n - Any modification will overridden on each Doktor run, obviously\n - Page likes are not preserved\n - Attachments are not preserved\n - There is no support for extra Confluence markup, macroses and features like comments\n\nThis may sound shocking to you, but let me explain.\n\nDoktor's idea is just uploading your documentation somewhere, making it available to _read_ by everybody.\nDoktor is not about collaborative editing - use VCS for that.\nIt's a unidirectional flow - from sources to rendered documents - by design.\nI was inspired by GitHub's https://pages.github.com[pages] and https://help.github.com/articles/about-github-wikis[wikis], and I sincerely believe in this approach.\n\nAt the moment, Doktor supports only Confluence and may never support any other services (unless my employer switches to another vendor).\n\n== Developing\n\nDoktor is built with https://kotlinlang.org[Kotlin], https://gradle.org[Gradle] and Love.\nWell, actually with hate to the workflows on my day-time job.\n\nJPI artifact is produced with https://github.com/jenkinsci/gradle-jpi-plugin[Gradle's JPI plugin].\nRead its documentation to know more about supported features and options.\n\nAlso, take a look at https://github.com/SimpleFinance/jenkins-firebase-test-plugin[this awesome Jenkins plugin], which is build with Gradle and Kotlin too!\n\n=== Building \u0026 running\n\nBasically, `./gradlew --rerun-tasks clean jpi server` will spin up a Jenkins with Doktor installed.\n`--rerun-tasks` is used to force clean build every time because Gradle aggressively caches build outputs, especially https://kotlinlang.org/docs/reference/kapt.html[Kotlin annotation processing tool] results.\nFeel free to tweak CLI arguments, assuming you know what you do.\n\nDebug is supported as well:\n\n[source, bash]\n----\nGRADLE_OPTS=\"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005\" ./gradlew --rerun-tasks clean jpi server\n----\n\nOmit `server` task if you just need a JPI file.\n\n=== Testing on remote agents\n\nOnce you may want to test how Doktor behaves on agents.\nThe simplest way to do that is to run an agent in Docker.\nThere are two images for agents available.\n\n==== jenkinsci/slave\n\nhttps://hub.docker.com/r/jenkinsci/slave[jenkinsci/slave] is an image meant to be run by Jenkins to start a new agent.\nThe configuration is very simple:\n\nimage::https://github.com/madhead/doktor/blob/master/.github/images/slave.png[]\n\nWhen you're running Jenkins via Gradle JPI plugin it will be run under you user account, so either your user needs to be able to execute `sudo docker` without password or you will need to type that password in Gradle's terminal session.\n\n==== jenkinsci/ssh-slave\n\nhttps://hub.docker.com/r/jenkinsci/ssh-slave[jenkinsci/ssh-slave] is another (better) option.\nIt allows you manage agent container separately and then attach it to Jenkins, thus eliminating the need to provide any password or execute `sudo docker`.\nContainer's mounts and FS modifications will be preserved between Jenkins restarts.\n\nFirst, you need to have an SSH key pair that will be used to connect to the agent.\nLooks like only RSA keys are supported (public key must start with `ssh-` prefix).\nEither https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent[create a new one], or use the existing.\n\nThen, install https://wiki.jenkins.io/display/JENKINS/SSH+Slaves+plugin[SSH Slaves plugin] on the master.\n\nCreate new \"SSH Username with private key\" credentials:\n\nimage::https://github.com/madhead/doktor/blob/master/.github/images/ssh_slave_credentials.png[]\n\nYou can paste private key directly here or use one of the defaults (`~/.ssh/id_ecdsa`, `~/.ssh/id_rsa`, `~/.ssh/id_dsa`, `~/.ssh/identity`).\n\nNext, start agent container by executing `docker run --detach --name jenkins-slave jenkinsci/ssh-slave \"$(cat ~/.ssh/jenkins.pub)\"` (assuming that `~/.ssh/jenkins.pub` is a public key corresponding to the private key from previous step).\n\nFinally, create new agent with a configuration like this:\n\nimage::https://github.com/madhead/doktor/blob/master/.github/images/ssh_slave.png[]\n\n`172.17.0.2` here is the IP of a Docker contaner from the previous step, https://stackoverflow.com/a/20686101/750510[found in `docker inspect` output].\nYou could also run the container exposing the ports (e.g. `-p 2222:22`) and then use `localhost` as host and `2222` as port.\n\n=== Testing Confluence integration\n\nYou'll need to refer to Confluence REST API.\nhttps://docs.atlassian.com/confluence/REST/latest[Here] is the link.\nhttps://developer.atlassian.com/confdev/confluence-server-rest-api/confluence-rest-api-examples[Samples] are also available.\n\n==== Cloud\n\nProbably, the easiest (and CPU / RAM saving) way to run Confluence is to run it in the cloud (AWS EC2, DigitalOcean, ...).\nThough, it will cost you some money.\n\nThere is an link:.ansible/confluence.yml[Ansible script] in this repo to automate Confluence installation.\nIt assumes that you already have a running instance that meets https://confluence.atlassian.com/doc/system-requirements-126517514.html[Confluence's minimal system requirements].\nRead your cloud provider's documentation to know how to create and manageVMs.\n\nWhen you have a VM, just follow these steps to install Confluence Server:\n\n. Create inventory file (`.ansible/inventory`) with a content like this:\n+\n[source, ini]\n----\n[confluence]\nyour.confluence.host\n----\n+\nYou might want to add additional parameters.\nFor example, a set of parameters for Ubuntu 16.04 EC2 instance:\n+\n[source, ini]\n----\n[confluence]\nyour.confluence.host ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/confluence.pem ansible_python_interpreter=/usr/bin/python3\n----\n+\nOr you can just use http://docs.ansible.com/ansible/latest/intro_dynamic_inventory.html[dynamic inventories].\n\n. Install required roles from https://galaxy.ansible.com[Ansible Galaxy]: `sudo ansible-galaxy install -r requirements.yml --force`.\n\n. After the inventory is configured, just run `./confluence.yml` from the `.ansible` directory.\n\n. Go to `http://your.confluence.host/` (if the DNS and IPs are set) and configure the instance.\nNote, that you will need a license key (trial works for 90 days).\n\n==== Docker\n\nYou can run Confluence locally as well.\nThe easiest way here is https://www.docker.com[Docker] (Windows uses should appreciate the joke).\n\nRunning Confluence is as simple as:\n\n[source, bash]\n----\ndocker volume create --name confluence-data\ndocker run --detach --volume confluence-data:/var/atlassian/application-data/confluence --name confluence --publish-all atlassian/confluence-server:latest\n----\n\nYou might want to add some https://docs.docker.com/engine/reference/run[additional options] or tweak the existing ones.\n\nNote, that you will need a license key (trial works for 90 days).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmadhead%2Fdoktor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmadhead%2Fdoktor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmadhead%2Fdoktor/lists"}