diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000000000000000000000000000000000000..bdae9aa90dd7e0b536408cf6c42c966d0154894a
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# vim: ft=yaml
+---
+# General overrides used across formulas in the org
+Metrics/LineLength:
+  # Increase from default of `80`
+  # Based on https://github.com/PyCQA/flake8-bugbear#opinionated-warnings (`B950`)
+  Max: 88
+
+# Any offenses that should be fixed, e.g. collected via. `rubocop --auto-gen-config`
diff --git a/.salt-lint b/.salt-lint
new file mode 100644
index 0000000000000000000000000000000000000000..3f397d15c5eb4dafc04fe2753e182786163c131c
--- /dev/null
+++ b/.salt-lint
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# vim: ft=yaml
+---
+exclude_paths: []
+skip_list:
+  # TODO: Formula-specific override to remove eventually
+  #       A lot of attention is going to be needed to resolve the existing long lines
+  - 204  # Lines should be no longer that 160 chars
+  # Using `salt-lint` for linting other files as well, such as Jinja macros/templates
+  - 205  # Use ".sls" as a Salt State file extension
+  # Skipping `207` and `208` because `210` is sufficient, at least for the time-being
+  # I.e. Allows 3-digit unquoted codes to still be used, such as `644` and `755`
+  - 207  # File modes should always be encapsulated in quotation marks
+  - 208  # File modes should always contain a leading zero
+tags: []
+verbosity: 1
diff --git a/.travis.yml b/.travis.yml
index befa68902c46e8c5356d440fe6a5d13d4dd27ec7..b1ff31014b05aa4585187cac4ebb4a50dd20d43c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,64 +1,43 @@
 # -*- coding: utf-8 -*-
 # vim: ft=yaml
 ---
+## Machine config
 dist: bionic
-stages:
-  - test
-  - lint
-  - name: release
-    if: branch = master AND type != pull_request
-
 sudo: required
-cache: bundler
-language: ruby
-
 services:
   - docker
 
-# Make sure the instances listed below match up with
-# the `platforms` defined in `kitchen.yml`
-env:
-  matrix:
-    - INSTANCE: default-debian-10-develop-py3
-    - INSTANCE: default-ubuntu-1804-develop-py3
-    # - INSTANCE: default-centos-7-develop-py3
-    # - INSTANCE: default-fedora-30-develop-py3
-    # - INSTANCE: default-opensuse-leap-15-develop-py3
-    # - INSTANCE: default-amazonlinux-2-develop-py2
-    # - INSTANCE: default-arch-base-latest-develop-py2
-    - INSTANCE: default-debian-9-2019-2-py3
-    - INSTANCE: default-ubuntu-1804-2019-2-py3
-    # - INSTANCE: default-centos-7-2019-2-py3
-    # - INSTANCE: default-fedora-30-2019-2-py3
-    # - INSTANCE: default-opensuse-leap-15-2019-2-py3
-    # - INSTANCE: default-amazonlinux-2-2019-2-py2
-    # - INSTANCE: default-arch-base-latest-2019-2-py2
-    - INSTANCE: default-debian-9-2018-3-py2
-    # - INSTANCE: default-ubuntu-1604-2018-3-py2
-    # - INSTANCE: default-centos-7-2018-3-py2
-    # - INSTANCE: default-fedora-29-2018-3-py2
-    # - INSTANCE: default-opensuse-leap-15-2018-3-py2
-    # - INSTANCE: default-amazonlinux-2-2018-3-py2
-    # - INSTANCE: default-arch-base-latest-2018-3-py2
-    - INSTANCE: default-debian-8-2017-7-py2
-    # - INSTANCE: default-ubuntu-1604-2017-7-py2
-    # - INSTANCE: default-centos-6-2017-7-py2
-    # - INSTANCE: default-fedora-29-2017-7-py2
-    # - INSTANCE: default-opensuse-leap-15-2017-7-py2
-    # - INSTANCE: default-amazonlinux-2-2017-7-py2
-    # - INSTANCE: default-arch-base-latest-2017-7-py2
+## Language and cache config
+language: ruby
+cache: bundler
 
+## Script to run for the test stage
 script:
-  - bin/kitchen verify ${INSTANCE}
+  - bin/kitchen verify "${INSTANCE}"
 
+## Stages and jobs matrix
+stages:
+  - test
+  - name: release
+    if: branch = master AND type != pull_request
 jobs:
+  allow_failures:
+    - env: Lint_rubocop
+  fast_finish: true
   include:
-    # Define the `lint` stage (runs `yamllint` and `commitlint`)
-    - stage: lint
-      language: node_js
+    ## Define the test stage that runs the linters (and testing matrix, if applicable)
+
+    # Run all of the linters in a single job (except `rubocop`)
+    - language: node_js
       node_js: lts/*
+      env: Lint
+      name: 'Lint: salt-lint, yamllint & commitlint'
       before_install: skip
       script:
+        # Install and run `salt-lint`
+        - pip install --user salt-lint
+        - git ls-files | grep '\.sls$\|\.jinja$\|\.j2$\|\.tmpl$'
+                       | xargs -I {} salt-lint {}
         # Install and run `yamllint`
         # Need at least `v1.17.0` for the `yaml-files` setting
         - pip install --user yamllint>=1.17.0
@@ -67,10 +46,56 @@ jobs:
         - npm install @commitlint/config-conventional -D
         - npm install @commitlint/travis-cli -D
         - commitlint-travis
-    # Define the release stage that runs `semantic-release`
+    # Run the `rubocop` linter in a separate job that is allowed to fail
+    # Once these lint errors are fixed, this can be merged into a single job
+    - language: node_js
+      node_js: lts/*
+      env: Lint_rubocop
+      name: 'Lint: rubocop'
+      before_install: skip
+      script:
+        # Install and run `rubocop`
+        - gem install rubocop
+        - rubocop -d
+
+    ## Define the rest of the matrix based on Kitchen testing
+    # Make sure the instances listed below match up with
+    # the `platforms` defined in `kitchen.yml`
+    - env: INSTANCE=default-debian-10-develop-py3
+    - env: INSTANCE=default-ubuntu-1804-develop-py3
+    # - env: INSTANCE=default-centos-7-develop-py3
+    # - env: INSTANCE=default-fedora-30-develop-py3
+    # - env: INSTANCE=default-opensuse-leap-15-develop-py3
+    # - env: INSTANCE=default-amazonlinux-2-develop-py2
+    # - env: INSTANCE=default-arch-base-latest-develop-py2
+    - env: INSTANCE=default-debian-9-2019-2-py3
+    - env: INSTANCE=default-ubuntu-1804-2019-2-py3
+    # - env: INSTANCE=default-centos-7-2019-2-py3
+    # - env: INSTANCE=default-fedora-30-2019-2-py3
+    # - env: INSTANCE=default-opensuse-leap-15-2019-2-py3
+    # - env: INSTANCE=default-amazonlinux-2-2019-2-py2
+    # - env: INSTANCE=default-arch-base-latest-2019-2-py2
+    - env: INSTANCE=default-debian-9-2018-3-py2
+    # - env: INSTANCE=default-ubuntu-1604-2018-3-py2
+    # - env: INSTANCE=default-centos-7-2018-3-py2
+    # - env: INSTANCE=default-fedora-29-2018-3-py2
+    # - env: INSTANCE=default-opensuse-leap-15-2018-3-py2
+    # - env: INSTANCE=default-amazonlinux-2-2018-3-py2
+    # - env: INSTANCE=default-arch-base-latest-2018-3-py2
+    - env: INSTANCE=default-debian-8-2017-7-py2
+    # - env: INSTANCE=default-ubuntu-1604-2017-7-py2
+    # - env: INSTANCE=default-centos-6-2017-7-py2
+    # - env: INSTANCE=default-fedora-29-2017-7-py2
+    # - env: INSTANCE=default-opensuse-leap-15-2017-7-py2
+    # - env: INSTANCE=default-amazonlinux-2-2017-7-py2
+    # - env: INSTANCE=default-arch-base-latest-2017-7-py2
+
+    ## Define the release stage that runs `semantic-release`
     - stage: release
       language: node_js
       node_js: lts/*
+      env: Release
+      name: 'Run semantic-release inc. file updates to AUTHORS, CHANGELOG & FORMULA'
       before_install: skip
       script:
         # Update `AUTHORS.md`
diff --git a/.yamllint b/.yamllint
index 896a2e5b42fb27576129344e0587243a6118c821..1d467f2fd41f0d858817caf5005a19ca94cffc10 100644
--- a/.yamllint
+++ b/.yamllint
@@ -19,6 +19,7 @@ yaml-files:
   # Default settings
   - '*.yaml'
   - '*.yml'
+  - .salt-lint
   - .yamllint
   # SaltStack Formulas additional settings
   - '*.example'
diff --git a/Gemfile b/Gemfile
index 3b36de3248927cda58b93d9cd662b597afe88128..5a232b615c1a211901e27d91c42fc60476948162 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,7 @@
-source "https://rubygems.org"
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
 
 gem 'kitchen-docker', '>= 2.9'
-gem 'kitchen-salt', '>= 0.6.0'
 gem 'kitchen-inspec', '>= 1.1'
-
+gem 'kitchen-salt', '>= 0.6.0'
diff --git a/bin/kitchen b/bin/kitchen
index 1cd44f3ad3bd7748ded19ca6e1167035cdeb8f83..dcfdb4ca766d2dc652151e64e779d4232cd3b43d 100755
--- a/bin/kitchen
+++ b/bin/kitchen
@@ -8,22 +8,25 @@
 # this file is here to facilitate running it.
 #
 
-require "pathname"
-ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
-  Pathname.new(__FILE__).realpath)
+require 'pathname'
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
+                                           Pathname.new(__FILE__).realpath)
 
-bundle_binstub = File.expand_path("../bundle", __FILE__)
+bundle_binstub = File.expand_path('bundle', __dir__)
 
 if File.file?(bundle_binstub)
   if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
     load(bundle_binstub)
   else
-    abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
-Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
+    abort(
+      'Your `bin/bundle` was not generated by Bundler, '\
+      'so this binstub cannot run.  Replace `bin/bundle` by running '\
+      '`bundle binstubs bundler --force`, then run this command again.'
+    )
   end
 end
 
-require "rubygems"
-require "bundler/setup"
+require 'rubygems'
+require 'bundler/setup'
 
-load Gem.bin_path("test-kitchen", "kitchen")
+load Gem.bin_path('test-kitchen', 'kitchen')
diff --git a/mysql/server.sls b/mysql/server.sls
index c69c98e84361b2aa88a9a086e0175c68b36c0467..a517b8c9de904c7779077aed6e04710c94f10b0d 100644
--- a/mysql/server.sls
+++ b/mysql/server.sls
@@ -116,7 +116,7 @@ mysql_initialize:
   cmd.run:
     - name: mysqld --initialize-insecure --user=mysql --basedir=/usr --datadir={{ mysql_datadir }}
     - runas: root
-    - creates: {{ mysql_datadir}}/mysql/
+    - creates: {{ mysql_datadir }}/mysql/
     - require:
       - pkg: {{ mysql.serverpkg }}
 {% endif %}
@@ -138,7 +138,7 @@ mysql_initialize:
   cmd.run:
     - name: emerge --config {{ mysql.serverpkg }}
     - runas: root
-    - creates: {{ mysql_datadir}}/mysql/
+    - creates: {{ mysql_datadir }}/mysql/
     - require:
       - pkg: {{ mysql.serverpkg }}
 {% endif %}
diff --git a/mysql/user.sls b/mysql/user.sls
index fa0b6e4e24683ec02fa2b7310c6d035751606206..c31ef0e293d9d33f9dafd800f491edbd07ed0fdf 100644
--- a/mysql/user.sls
+++ b/mysql/user.sls
@@ -32,7 +32,7 @@ include:
 
 {% for host in user_hosts %}
 
-{% set state_id = 'mysql_user_' ~ name ~ '_' ~ host%}
+{% set state_id = 'mysql_user_' ~ name ~ '_' ~ host %}
 {{ state_id }}:
   {%- if user.get('present', True) %}
     mysql_user.present:
@@ -97,7 +97,7 @@ include:
 {{ state_id ~ '_' ~ loop.index0 }}:
   mysql_grants.present:
     - name: {{ name ~ '_' ~ db['database']  ~ '_' ~ db['table'] | default('all') }}
-    - grant: {{db['grants']|join(",")}}
+    - grant: {{ db['grants']|join(",") }}
     - database: '{{ db['database'] }}.{{ db['table'] | default('*') }}'
     - grant_option: {{ db['grant_option'] | default(False) }}
     {% if 'ssl' in user or 'ssl-X509' in user %}