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 @@ -125,6 +125,8 @@ 'ArcanistPhutilTestTerminatedException' => 'unit/engine/phutil/testcase/ArcanistPhutilTestTerminatedException.php', 'ArcanistPhutilXHPASTLinter' => 'lint/linter/ArcanistPhutilXHPASTLinter.php', 'ArcanistPhutilXHPASTLinterTestCase' => 'lint/linter/__tests__/ArcanistPhutilXHPASTLinterTestCase.php', + 'ArcanistPuppetLintLinter' => 'lint/linter/ArcanistPuppetLintLinter.php', + 'ArcanistPuppetLintLinterTestCase' => 'lint/linter/__tests__/ArcanistPuppetLintLinterTestCase.php', 'ArcanistPyFlakesLinter' => 'lint/linter/ArcanistPyFlakesLinter.php', 'ArcanistPyFlakesLinterTestCase' => 'lint/linter/__tests__/ArcanistPyFlakesLinterTestCase.php', 'ArcanistPyLintLinter' => 'lint/linter/ArcanistPyLintLinter.php', @@ -281,6 +283,8 @@ 'ArcanistPhutilTestTerminatedException' => 'Exception', 'ArcanistPhutilXHPASTLinter' => 'ArcanistBaseXHPASTLinter', 'ArcanistPhutilXHPASTLinterTestCase' => 'ArcanistArcanistLinterTestCase', + 'ArcanistPuppetLintLinter' => 'ArcanistExternalLinter', + 'ArcanistPuppetLintLinterTestCase' => 'ArcanistArcanistLinterTestCase', 'ArcanistPyFlakesLinter' => 'ArcanistExternalLinter', 'ArcanistPyFlakesLinterTestCase' => 'ArcanistArcanistLinterTestCase', 'ArcanistPyLintLinter' => 'ArcanistLinter', diff --git a/src/lint/linter/ArcanistPuppetLintLinter.php b/src/lint/linter/ArcanistPuppetLintLinter.php new file mode 100644 --- /dev/null +++ b/src/lint/linter/ArcanistPuppetLintLinter.php @@ -0,0 +1,92 @@ +getExecutableCommand()); + + $matches = array(); + $regex = '/^Puppet-lint (?P\d+\.\d+\.\d+)$/'; + if (preg_match($regex, $stdout, $matches)) { + return $matches['version']; + } else { + return false; + } + } + + public function getInstallInstructions() { + return pht('Install puppet-lint using `gem install puppet-lint`.'); + } + + public function shouldExpectCommandErrors() { + return true; + } + + public function supportsReadDataFromStdin() { + return false; + } + + protected function getMandatoryFlags() { + return array(sprintf('--log-format=%s', implode('|', array( + '%{linenumber}', + '%{column}', + '%{kind}', + '%{check}', + '%{message}')))); + } + + protected function parseLinterOutput($path, $err, $stdout, $stderr) { + $lines = phutil_split_lines($stdout, false); + + $messages = array(); + foreach ($lines as $line) { + $matches = explode('|', $line, 5); + + if (count($matches) === 5) { + $message = new ArcanistLintMessage(); + $message->setPath($path); + $message->setLine($matches[0]); + $message->setChar($matches[1]); + $message->setName(ucwords(str_replace('_', ' ', $matches[3]))); + $message->setDescription(ucfirst($matches[4])); + + switch ($matches[2]) { + case 'warning': + $message->setSeverity(ArcanistLintSeverity::SEVERITY_WARNING); + break; + + case 'error': + $message->setSeverity(ArcanistLintSeverity::SEVERITY_ERROR); + break; + + default: + $message->setSeverity(ArcanistLintSeverity::SEVERITY_ADVICE); + break; + } + + $messages[] = $message; + } + } + + if ($err && !$messages) { + return false; + } + + return $messages; + } +} diff --git a/src/lint/linter/__tests__/ArcanistPuppetLintLinterTestCase.php b/src/lint/linter/__tests__/ArcanistPuppetLintLinterTestCase.php new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/ArcanistPuppetLintLinterTestCase.php @@ -0,0 +1,12 @@ +executeTestsInDirectory( + dirname(__FILE__).'/puppet-lint/', + new ArcanistPuppetLintLinter()); + } + +} diff --git a/src/lint/linter/__tests__/puppet-lint/2sp_soft_tabs.lint-test b/src/lint/linter/__tests__/puppet-lint/2sp_soft_tabs.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/2sp_soft_tabs.lint-test @@ -0,0 +1,7 @@ +exec { 'test': + subscribe => File['/etc/test'], + refreshonly => true, +} +~~~~~~~~~~ +error:2:1 +error:3:1 diff --git a/src/lint/linter/__tests__/puppet-lint/arrow_alignment.lint-test b/src/lint/linter/__tests__/puppet-lint/arrow_alignment.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/arrow_alignment.lint-test @@ -0,0 +1,6 @@ +exec { 'test': + subscribe => File['/etc/test'], + refreshonly => true, +} +~~~~~~~~~~ +warning:3:15 diff --git a/src/lint/linter/__tests__/puppet-lint/double_quoted_strings.lint-test b/src/lint/linter/__tests__/puppet-lint/double_quoted_strings.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/double_quoted_strings.lint-test @@ -0,0 +1,7 @@ +user { 'dave': + ensure => present, + home => '/home/dave', + comment => "This is a double quoted string", +} +~~~~~~~~~~ +warning:4:14 diff --git a/src/lint/linter/__tests__/puppet-lint/duplicate_params.lint-test b/src/lint/linter/__tests__/puppet-lint/duplicate_params.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/duplicate_params.lint-test @@ -0,0 +1,6 @@ +service { 'anacron': + ensure => 'absent', + ensure => 'stopped', +} +~~~~~~~~~~ +error:3:3 diff --git a/src/lint/linter/__tests__/puppet-lint/ensure_not_symlink_target.lint-test b/src/lint/linter/__tests__/puppet-lint/ensure_not_symlink_target.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/ensure_not_symlink_target.lint-test @@ -0,0 +1,5 @@ +file { '/var/log/syslog': + ensure => '/var/log/messages', +} +~~~~~~~~~~ +warning:2:13 diff --git a/src/lint/linter/__tests__/puppet-lint/file_mode.lint-test b/src/lint/linter/__tests__/puppet-lint/file_mode.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/file_mode.lint-test @@ -0,0 +1,6 @@ +file { '/var/log/syslog': + ensure => present, + mode => '644', +} +~~~~~~~~~~ +warning:3:13 diff --git a/src/lint/linter/__tests__/puppet-lint/hard_tabs.lint-test b/src/lint/linter/__tests__/puppet-lint/hard_tabs.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/hard_tabs.lint-test @@ -0,0 +1,7 @@ +exec { 'test': + subscribe => File['/etc/test'], + refreshonly => true, +} +~~~~~~~~~~ +error:2:1 +error:3:1 diff --git a/src/lint/linter/__tests__/puppet-lint/names_containing_dash.lint-test b/src/lint/linter/__tests__/puppet-lint/names_containing_dash.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/names_containing_dash.lint-test @@ -0,0 +1,3 @@ +$foo-bar123 +~~~~~~~~~~ +warning:1:1 diff --git a/src/lint/linter/__tests__/puppet-lint/quoted_booleans.lint-test b/src/lint/linter/__tests__/puppet-lint/quoted_booleans.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/quoted_booleans.lint-test @@ -0,0 +1,6 @@ +service { 'anacron': + ensure => 'stopped', + enable => 'true', +} +~~~~~~~~~~ +warning:3:13 diff --git a/src/lint/linter/__tests__/puppet-lint/right_to_left_relationship.lint-test b/src/lint/linter/__tests__/puppet-lint/right_to_left_relationship.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/right_to_left_relationship.lint-test @@ -0,0 +1,3 @@ +Service['httpd'] <- Package['httpd'] +~~~~~~~~~~ +warning:1:18 diff --git a/src/lint/linter/__tests__/puppet-lint/site.lint-test b/src/lint/linter/__tests__/puppet-lint/site.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/site.lint-test @@ -0,0 +1,19 @@ +import 'classes/*' +import 'nodes.pp' + +Exec['apt-get-update'] -> Package <| |> + +Exec { + path => '/usr/bin:/usr/sbin:/bin', +} + +exec { 'apt-get-update': + command => '/usr/bin/apt-get update', + require => File['/etc/apt/apt.conf.d/01proxy'], +} + +file { '/etc/apt/apt.conf.d/01proxy': + ensure => 'file', + source => '/tmp/vagrant-puppet/manifests/files/apt-conf', +} +~~~~~~~~~~ diff --git a/src/lint/linter/__tests__/puppet-lint/slash_comments.lint-test b/src/lint/linter/__tests__/puppet-lint/slash_comments.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/slash_comments.lint-test @@ -0,0 +1,3 @@ +// This is a comment +~~~~~~~~~~ +warning:1:1 diff --git a/src/lint/linter/__tests__/puppet-lint/star_comments.lint-test b/src/lint/linter/__tests__/puppet-lint/star_comments.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/star_comments.lint-test @@ -0,0 +1,3 @@ +/* This is a comment */ +~~~~~~~~~~ +warning:1:1 diff --git a/src/lint/linter/__tests__/puppet-lint/unquoted_file_mode.lint-test b/src/lint/linter/__tests__/puppet-lint/unquoted_file_mode.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/__tests__/puppet-lint/unquoted_file_mode.lint-test @@ -0,0 +1,6 @@ +file { '/var/log/syslog': + ensure => present, + mode => 0644, +} +~~~~~~~~~~ +warning:3:13