From 33580f22b0c5d04810a6f5716d00c742a30a6fa4 Mon Sep 17 00:00:00 2001
From: Clint Byrum <clint@fewbar.com>
Date: Wed, 3 Oct 2018 13:54:49 -0500
Subject: [PATCH] Add a markdownlint job and role

This tool will ensure that your markdown files follow some best
practices.

Change-Id: I7bcc70443dbe5fa31e3cc1139d608834c00851b9
---
 doc/source/general-jobs.rst                 |  1 +
 doc/source/general-roles.rst                |  3 +++
 playbooks/markdownlint/post.yaml            |  4 ++++
 playbooks/markdownlint/pre.yaml             |  5 +++++
 playbooks/markdownlint/run.yaml             |  5 +++++
 roles/ensure-markdownlint/README.rst        |  1 +
 roles/ensure-markdownlint/tasks/main.yaml   |  4 ++++
 roles/fetch-markdownlint/README.rst         |  9 +++++++++
 roles/fetch-markdownlint/defaults/main.yaml |  1 +
 roles/fetch-markdownlint/tasks/main.yaml    | 12 ++++++++++++
 roles/markdownlint/README.rst               |  8 ++++++++
 roles/markdownlint/defaults/main.yaml       |  1 +
 roles/markdownlint/tasks/main.yaml          | 16 ++++++++++++++++
 zuul.d/python-jobs.yaml                     | 11 +++++++++++
 14 files changed, 81 insertions(+)
 create mode 100644 playbooks/markdownlint/post.yaml
 create mode 100644 playbooks/markdownlint/pre.yaml
 create mode 100644 playbooks/markdownlint/run.yaml
 create mode 100644 roles/ensure-markdownlint/README.rst
 create mode 100644 roles/ensure-markdownlint/tasks/main.yaml
 create mode 100644 roles/fetch-markdownlint/README.rst
 create mode 100644 roles/fetch-markdownlint/defaults/main.yaml
 create mode 100644 roles/fetch-markdownlint/tasks/main.yaml
 create mode 100644 roles/markdownlint/README.rst
 create mode 100644 roles/markdownlint/defaults/main.yaml
 create mode 100644 roles/markdownlint/tasks/main.yaml

diff --git a/doc/source/general-jobs.rst b/doc/source/general-jobs.rst
index 747b1ac70..7803f82b7 100644
--- a/doc/source/general-jobs.rst
+++ b/doc/source/general-jobs.rst
@@ -3,6 +3,7 @@ General Purpose Jobs
 
 .. zuul:autojob:: dco-license
 .. zuul:autojob:: unittests
+.. zuul:autojob:: markdownlint
 .. zuul:autojob:: multinode
 .. zuul:autojob:: run-test-command
 .. zuul:autojob:: upload-git-mirror
diff --git a/doc/source/general-roles.rst b/doc/source/general-roles.rst
index 577486a14..49ace3eef 100644
--- a/doc/source/general-roles.rst
+++ b/doc/source/general-roles.rst
@@ -15,8 +15,11 @@ General Purpose Roles
 .. zuul:autorole:: emit-job-header
 .. zuul:autorole:: enable-netconsole
 .. zuul:autorole:: ensure-dstat-graph
+.. zuul:autorole:: ensure-markdownlint
+.. zuul:autorole:: fetch-markdownlint
 .. zuul:autorole:: git-prepare-nodecache
 .. zuul:autorole:: log-inventory
+.. zuul:autorole:: markdownlint
 .. zuul:autorole:: mirror-workspace-git-repos
 .. zuul:autorole:: multi-node-bridge
 .. zuul:autorole:: multi-node-firewall
diff --git a/playbooks/markdownlint/post.yaml b/playbooks/markdownlint/post.yaml
new file mode 100644
index 000000000..90b0517cb
--- /dev/null
+++ b/playbooks/markdownlint/post.yaml
@@ -0,0 +1,4 @@
+- name: Get markdownlint report
+  hosts: all
+  roles:
+    - fetch-markdownlint
diff --git a/playbooks/markdownlint/pre.yaml b/playbooks/markdownlint/pre.yaml
new file mode 100644
index 000000000..c8180f945
--- /dev/null
+++ b/playbooks/markdownlint/pre.yaml
@@ -0,0 +1,5 @@
+- name: Ensure Markdownlint is installed via NPM
+  hosts: all
+  roles:
+    - install-nodejs
+    - ensure-markdownlint
diff --git a/playbooks/markdownlint/run.yaml b/playbooks/markdownlint/run.yaml
new file mode 100644
index 000000000..d0f51f2c4
--- /dev/null
+++ b/playbooks/markdownlint/run.yaml
@@ -0,0 +1,5 @@
+- name: Run markdownlint
+  hosts: all
+  roles:
+    - revoke-sudo
+    - markdownlint
diff --git a/roles/ensure-markdownlint/README.rst b/roles/ensure-markdownlint/README.rst
new file mode 100644
index 000000000..085b698bc
--- /dev/null
+++ b/roles/ensure-markdownlint/README.rst
@@ -0,0 +1 @@
+Ensure markdownlint-cli from NPM is installed.
diff --git a/roles/ensure-markdownlint/tasks/main.yaml b/roles/ensure-markdownlint/tasks/main.yaml
new file mode 100644
index 000000000..d45cb8e41
--- /dev/null
+++ b/roles/ensure-markdownlint/tasks/main.yaml
@@ -0,0 +1,4 @@
+- name: Install markdownlint-cli
+  npm:
+    name: markdownlint-cli
+    path: ~/.markdownlint
diff --git a/roles/fetch-markdownlint/README.rst b/roles/fetch-markdownlint/README.rst
new file mode 100644
index 000000000..2f3a253f6
--- /dev/null
+++ b/roles/fetch-markdownlint/README.rst
@@ -0,0 +1,9 @@
+Collect output from a markdownlint run. Assumes you will only run one repo, and
+one node.
+
+**Role Variables**
+
+.. zuul:rolevar:: zuul_work_dir
+   :default: {{ zuul.project.src_dir }}
+
+   The location of the main working directory of the job.
diff --git a/roles/fetch-markdownlint/defaults/main.yaml b/roles/fetch-markdownlint/defaults/main.yaml
new file mode 100644
index 000000000..9739eb171
--- /dev/null
+++ b/roles/fetch-markdownlint/defaults/main.yaml
@@ -0,0 +1 @@
+zuul_work_dir: "{{ zuul.project.src_dir }}"
diff --git a/roles/fetch-markdownlint/tasks/main.yaml b/roles/fetch-markdownlint/tasks/main.yaml
new file mode 100644
index 000000000..5ad52b1e9
--- /dev/null
+++ b/roles/fetch-markdownlint/tasks/main.yaml
@@ -0,0 +1,12 @@
+- name: Is there a markdownlint.txt
+  register: stat_mdl_txt
+  stat:
+    path: "{{ zuul_work_dir }}/markdownlint.txt"
+
+- name: Store on executor
+  when: stat_mdl_txt.stat.exists
+  synchronize:
+    mode: pull
+    src: "{{ zuul_work_dir }}/markdownlint.txt"
+    dest: "{{ zuul.executor.log_root }}/markdownlint.txt"
+    verify_host: true
diff --git a/roles/markdownlint/README.rst b/roles/markdownlint/README.rst
new file mode 100644
index 000000000..b8d86158a
--- /dev/null
+++ b/roles/markdownlint/README.rst
@@ -0,0 +1,8 @@
+Run markdownlint against all markdown files in the given project.
+
+**Role Variables**
+
+.. zuul:rolevar:: zuul_work_dir
+   :default: {{ zuul.project.src_dir }}
+
+   Directory to search for markdown files in.
diff --git a/roles/markdownlint/defaults/main.yaml b/roles/markdownlint/defaults/main.yaml
new file mode 100644
index 000000000..9739eb171
--- /dev/null
+++ b/roles/markdownlint/defaults/main.yaml
@@ -0,0 +1 @@
+zuul_work_dir: "{{ zuul.project.src_dir }}"
diff --git a/roles/markdownlint/tasks/main.yaml b/roles/markdownlint/tasks/main.yaml
new file mode 100644
index 000000000..9f58e6bdb
--- /dev/null
+++ b/roles/markdownlint/tasks/main.yaml
@@ -0,0 +1,16 @@
+- name: find all .md files
+  find:
+    paths: "{{ zuul_work_dir }}"
+    pattern: "*.md"
+  register: markdown_find
+
+- name: Run markdownlint
+  shell: |
+    set -o pipefail
+    set -e
+    ~/.markdownlint/node_modules/.bin/markdownlint {{ item|relpath(zuul_work_dir) }} 2>&1 | tee -a markdownlint.txt
+  args:
+    chdir: "{{ zuul_work_dir }}"
+    executable: /bin/bash
+  with_items: "{{ markdown_find.files|map(attribute='path')|list }}"
+  changed_when: false
diff --git a/zuul.d/python-jobs.yaml b/zuul.d/python-jobs.yaml
index 1af163f36..6da6e8715 100644
--- a/zuul.d/python-jobs.yaml
+++ b/zuul.d/python-jobs.yaml
@@ -335,3 +335,14 @@
       - test-requirements.txt
       - tox.ini
 
+- job:
+    name: markdownlint
+    files: '^.*\.md$'
+    pre-run: playbooks/markdownlint/pre.yaml
+    run: playbooks/markdownlint/run.yaml
+    post-run: playbooks/markdownlint/post.yaml
+    description: |
+      Check any markdown for basic lint problems. Include a file named
+      `.markdownlint.json` that is configured according to
+      https://github.com/DavidAnson/markdownlint#optionsconfig
+      to control rule specifics.