Page MenuHomePhabricator

D14662.diff
No OneTemporary

D14662.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -18,6 +18,8 @@
'ArcanistAliasWorkflow' => 'workflow/ArcanistAliasWorkflow.php',
'ArcanistAmendWorkflow' => 'workflow/ArcanistAmendWorkflow.php',
'ArcanistAnoidWorkflow' => 'workflow/ArcanistAnoidWorkflow.php',
+ 'ArcanistAnsibleLintLinter' => 'lint/linter/ArcanistAnsibleLintLinter.php',
+ 'ArcanistAnsibleLintLinterTestCase' => 'lint/linter/__tests__/ArcanistAnsibleLintLinterTestCase.php',
'ArcanistArrayCombineXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistArrayCombineXHPASTLinterRule.php',
'ArcanistArrayCombineXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistArrayCombineXHPASTLinterRuleTestCase.php',
'ArcanistArrayIndexSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistArrayIndexSpacingXHPASTLinterRule.php',
@@ -424,6 +426,8 @@
'ArcanistAliasWorkflow' => 'ArcanistWorkflow',
'ArcanistAmendWorkflow' => 'ArcanistWorkflow',
'ArcanistAnoidWorkflow' => 'ArcanistWorkflow',
+ 'ArcanistAnsibleLintLinter' => 'ArcanistExternalLinter',
+ 'ArcanistAnsibleLintLinterTestCase' => 'ArcanistExternalLinterTestCase',
'ArcanistArrayCombineXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistArrayCombineXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistArrayIndexSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
diff --git a/src/lint/linter/ArcanistAnsibleLintLinter.php b/src/lint/linter/ArcanistAnsibleLintLinter.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/ArcanistAnsibleLintLinter.php
@@ -0,0 +1,103 @@
+<?php
+
+/**
+ * Uses "ansible-lint" to suggest improvements to Ansible playbooks.
+ */
+final class ArcanistAnsibleLintLinter extends ArcanistExternalLinter {
+
+ public function getInfoName() {
+ return 'Ansible-Lint';
+ }
+
+ public function getInfoURI() {
+ return 'https://pypi.python.org/pypi/ansible-lint';
+ }
+
+ public function getInfoDescription() {
+ return pht(
+ 'Checks Ansible playbooks for practices and behavior '.
+ 'that could potentially be improved.');
+ }
+
+ public function getLinterName() {
+ return 'ANSIBLE';
+ }
+
+ public function getLinterConfigurationName() {
+ return 'ansible-lint';
+ }
+
+ public function getDefaultBinary() {
+ return 'ansible-lint';
+ }
+
+ protected function getDefaultFlags() {
+ return array(
+ '-p', // parseable PEP8-format output
+ );
+ }
+
+ public function getVersion() {
+ list($stdout) = execx('%C --version', $this->getExecutableCommand());
+
+ $matches = array();
+ if (preg_match('/^ansible-lint (?P<version>\d+\.\d+(?:\.\d+)?)\b/',
+ $stdout, $matches)) {
+ return $matches['version'];
+ } else {
+ return false;
+ }
+ }
+
+ public function getInstallInstructions() {
+ return pht('Install ansible-lint using `%s`.', 'pip install ansible-lint');
+ }
+
+ protected function parseLinterOutput($path, $err, $stdout, $stderr) {
+ $lines = phutil_split_lines($stdout, false);
+
+ $messages = array();
+ foreach ($lines as $line) {
+ $matches = null;
+ if (!preg_match('/^(.*?):(\d+): (\S+) (.*)$/', $line, $matches)) {
+ continue;
+ }
+ foreach ($matches as $key => $match) {
+ $matches[$key] = trim($match);
+ }
+ $message = new ArcanistLintMessage();
+ $message->setPath($matches[1]);
+ $message->setLine($matches[2]);
+ $message->setCode($matches[3]);
+ $message->setName('Ansible-Lint '.$matches[3]);
+ $message->setDescription($matches[4]);
+ $message->setSeverity($this->getLintMessageSeverity($matches[3]));
+ $messages[] = $message;
+ }
+
+ return $messages;
+ }
+
+ protected function getDefaultMessageSeverity($code) {
+ if (preg_match('/^ANSIBLE0003$/', $code)) {
+ return ArcanistLintSeverity::SEVERITY_ERROR;
+ } else {
+ return ArcanistLintSeverity::SEVERITY_WARNING;
+ }
+ }
+
+ protected function getLintCodeFromLinterConfigurationKey($code) {
+ if (!preg_match('/^(ANSIBLE)\d+$/', $code)) {
+ throw new Exception(
+ pht(
+ 'Unrecognized lint message code "%s". Expected a valid Ansible-Lint '.
+ 'lint code like "%s" or "%s".',
+ $code,
+ 'ANSIBLE0002',
+ 'ANSIBLE0007'));
+ }
+
+ return $code;
+ }
+
+}
diff --git a/src/lint/linter/__tests__/ArcanistAnsibleLintLinterTestCase.php b/src/lint/linter/__tests__/ArcanistAnsibleLintLinterTestCase.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/ArcanistAnsibleLintLinterTestCase.php
@@ -0,0 +1,10 @@
+<?php
+
+final class ArcanistAnsibleLintLinterTestCase
+ extends ArcanistExternalLinterTestCase {
+
+ public function testLinter() {
+ $this->executeTestsInDirectory(dirname(__FILE__).'/ansible-lint/');
+ }
+
+}
diff --git a/src/lint/linter/__tests__/ansible-lint/mismatched_curly_braces.lint-test b/src/lint/linter/__tests__/ansible-lint/mismatched_curly_braces.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/ansible-lint/mismatched_curly_braces.lint-test
@@ -0,0 +1,3 @@
+foo: '{'
+~~~~~~~~~~
+warning:1:
diff --git a/src/lint/linter/__tests__/ansible-lint/should_use_file_arg.lint-test b/src/lint/linter/__tests__/ansible-lint/should_use_file_arg.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/ansible-lint/should_use_file_arg.lint-test
@@ -0,0 +1,8 @@
+---
+
+- hosts: localhost
+ tasks:
+ - name: chmod
+ command: chmod 0700 ~/.ssh
+~~~~~~~~~~
+warning:5:
diff --git a/src/lint/linter/__tests__/ansible-lint/should_use_module.lint-test b/src/lint/linter/__tests__/ansible-lint/should_use_module.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/ansible-lint/should_use_module.lint-test
@@ -0,0 +1,8 @@
+---
+
+- hosts: localhost
+ tasks:
+ - name: git repo
+ command: git clone https://github.com/phacility/arcanist.git
+~~~~~~~~~~
+warning:5:
diff --git a/src/lint/linter/__tests__/ansible-lint/trailing_whitespace.lint-test b/src/lint/linter/__tests__/ansible-lint/trailing_whitespace.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/ansible-lint/trailing_whitespace.lint-test
@@ -0,0 +1,3 @@
+hosts: all
+~~~~~~~~~~
+warning:1:
diff --git a/src/lint/linter/__tests__/ansible-lint/unversioned_git.lint-test b/src/lint/linter/__tests__/ansible-lint/unversioned_git.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/ansible-lint/unversioned_git.lint-test
@@ -0,0 +1,10 @@
+---
+
+- hosts: localhost
+ tasks:
+ - name: git repo
+ git:
+ dest: ~/sources/arcanist
+ repo: https://github.com/phacility/arcanist.git
+~~~~~~~~~~
+warning:5:
diff --git a/src/lint/linter/__tests__/ansible-lint/unversioned_hg.lint-test b/src/lint/linter/__tests__/ansible-lint/unversioned_hg.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/ansible-lint/unversioned_hg.lint-test
@@ -0,0 +1,10 @@
+---
+
+- hosts: localhost
+ tasks:
+ - name: hg repo
+ hg:
+ dest: ~/sources/hg
+ repo: http://selenic.com/repo/hg
+~~~~~~~~~~
+warning:5:

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 22, 6:01 PM (19 h, 15 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6775530
Default Alt Text
D14662.diff (7 KB)

Event Timeline