1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-25 16:22:42 +01:00

Add a puppet-lint linter.

Summary: This linter is a wrapper around [[http://puppet-lint.com/ | puppet-lint[]].

Test Plan: Wrote an executed unit tests.

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: epriestley, Korvin

Differential Revision: https://secure.phabricator.com/D8990
This commit is contained in:
Joshua Spence 2014-05-05 20:42:40 -07:00 committed by epriestley
parent 48d52c30b0
commit 8523b98f39
17 changed files with 195 additions and 0 deletions

View file

@ -125,6 +125,8 @@ phutil_register_library_map(array(
'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 @@ phutil_register_library_map(array(
'ArcanistPhutilTestTerminatedException' => 'Exception',
'ArcanistPhutilXHPASTLinter' => 'ArcanistBaseXHPASTLinter',
'ArcanistPhutilXHPASTLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistPuppetLintLinter' => 'ArcanistExternalLinter',
'ArcanistPuppetLintLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistPyFlakesLinter' => 'ArcanistExternalLinter',
'ArcanistPyFlakesLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistPyLintLinter' => 'ArcanistLinter',

View file

@ -0,0 +1,92 @@
<?php
/**
* A linter for Puppet files.
*/
final class ArcanistPuppetLintLinter extends ArcanistExternalLinter {
public function getLinterName() {
return 'PUPPETLINT';
}
public function getLinterConfigurationName() {
return 'puppet-lint';
}
public function getDefaultBinary() {
return 'puppet-lint';
}
public function getVersion() {
list($stdout) = execx('%C --version', $this->getExecutableCommand());
$matches = array();
$regex = '/^Puppet-lint (?P<version>\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;
}
}

View file

@ -0,0 +1,12 @@
<?php
final class ArcanistPuppetLintLinterTestCase
extends ArcanistArcanistLinterTestCase {
public function testPuppetLintLinter() {
return $this->executeTestsInDirectory(
dirname(__FILE__).'/puppet-lint/',
new ArcanistPuppetLintLinter());
}
}

View file

@ -0,0 +1,7 @@
exec { 'test':
subscribe => File['/etc/test'],
refreshonly => true,
}
~~~~~~~~~~
error:2:1
error:3:1

View file

@ -0,0 +1,6 @@
exec { 'test':
subscribe => File['/etc/test'],
refreshonly => true,
}
~~~~~~~~~~
warning:3:15

View file

@ -0,0 +1,7 @@
user { 'dave':
ensure => present,
home => '/home/dave',
comment => "This is a double quoted string",
}
~~~~~~~~~~
warning:4:14

View file

@ -0,0 +1,6 @@
service { 'anacron':
ensure => 'absent',
ensure => 'stopped',
}
~~~~~~~~~~
error:3:3

View file

@ -0,0 +1,5 @@
file { '/var/log/syslog':
ensure => '/var/log/messages',
}
~~~~~~~~~~
warning:2:13

View file

@ -0,0 +1,6 @@
file { '/var/log/syslog':
ensure => present,
mode => '644',
}
~~~~~~~~~~
warning:3:13

View file

@ -0,0 +1,7 @@
exec { 'test':
subscribe => File['/etc/test'],
refreshonly => true,
}
~~~~~~~~~~
error:2:1
error:3:1

View file

@ -0,0 +1,3 @@
$foo-bar123
~~~~~~~~~~
warning:1:1

View file

@ -0,0 +1,6 @@
service { 'anacron':
ensure => 'stopped',
enable => 'true',
}
~~~~~~~~~~
warning:3:13

View file

@ -0,0 +1,3 @@
Service['httpd'] <- Package['httpd']
~~~~~~~~~~
warning:1:18

View file

@ -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',
}
~~~~~~~~~~

View file

@ -0,0 +1,3 @@
// This is a comment
~~~~~~~~~~
warning:1:1

View file

@ -0,0 +1,3 @@
/* This is a comment */
~~~~~~~~~~
warning:1:1

View file

@ -0,0 +1,6 @@
file { '/var/log/syslog':
ensure => present,
mode => 0644,
}
~~~~~~~~~~
warning:3:13