8000 Add optional --config and --exclude options · symfony/symfony@f09c5e1 · GitHub
[go: up one dir, main page]

Skip to content

Commit f09c5e1

Browse files
Add optional --config and --exclude options
1 parent c01b032 commit f09c5e1

File tree

4 files changed

+132
-6
lines changed

4 files changed

+132
-6
lines changed

src/Symfony/Component/Yaml/CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@ CHANGELOG
66

77
* Added `github` format support & autodetection to render errors as annotations
88
when running the YAML linter command in a Github Action environment.
9+
* Added support for optional YAML lint config from file `lint:yaml --config=.yamllint.yml`.
10+
11+
```yml
12+
yaml-lint:
13+
format: txt
14+
includes:
15+
- src/Resources/config/foo.yml
16+
- src/Resources/config/bar.yml
17+
- src/Resources/config/path/
18+
excludes:
19+
- src/Resources/config/path/exclude.yml
20+
```
21+
22+
* Added new `lint:yaml dirname --exclude=/dirname/foo.yml --exclude=/dirname/bar.yml` option to exclude one or more specific files from multiple file list.
23+
* Allow negatable for `--parse-tags|--no-parse-tags` option
924

1025
5.1.0
1126
-----

src/Symfony/Component/Yaml/Command/LintCommand.php

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ protected function configure()
5757
->setDescription('Lints a file and outputs encountered errors')
5858
->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')
5959
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format')
60-
->addOption('parse-tags', null, InputOption::VALUE_NONE, 'Parse custom tags')
60+
->addOption('exclude', 'e', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Path(s) to exclude')
61+
->addOption('config', 'c', InputOption::VALUE_REQUIRED, 'Path to YAML lint config')
62+
->addOption('parse-tags', null, InputOption::VALUE_NEGATABLE, 'Parse custom tags', null)
6163
->setHelp(<<<EOF
6264
The <info>%command.name%</info> command lints a YAML file and outputs to STDOUT
6365
the first encountered syntax error.
@@ -66,6 +68,10 @@ protected function configure()
6668
6769
<info>cat filename | php %command.full_name% -</info>
6870
71+
You can validate YAML contents passed from config file:
72+
73+
<info>php %command.full_name% --config=.yamllint.yml</info>
74+
6975
You can also validate the syntax of a file:
7076
7177
<info>php %command.full_name% filename</info>
@@ -75,6 +81,10 @@ protected function configure()
7581
<info>php %command.full_name% dirname</info>
7682
<info>php %command.full_name% dirname --format=json</info>
7783
84+
You can also exclude one or more specific files:
85+
86+
<info>php %command.full_name% dirname --exclude="dirname/foo.yml" --exclude="dirname/bar.yml"</info>
87+
7888
EOF
7989
)
8090
;
@@ -84,7 +94,24 @@ protected function execute(InputInterface $input, OutputInterface $output)
8494
{
8595
$io = new SymfonyStyle($input, $output);
8696
$filenames = (array) $input->getArgument('filename');
97+
$config = $input->getOption('config');
98+
$excludes = $input->getOption('exclude');
8799
$this->format = $input->getOption('format');
100+
$flags = $input->getOption('parse-tags');
101+
102+
if ($config) {
103+
$lintConfig = $this->parseLintConfig($config);
104+
105+
$filenames = array_merge($lintConfig['includes'], $filenames);
106+
$excludes = array_merge($lintConfig['excludes'], $excludes);
107+
108+
if (null === $this->format && isset($lintConfig['format'])) {
109+
$this->format = $lintConfig['format'];
110+
}
111+
if (null !== $flags && isset($lintConfig['parse-tags'])) {
112+
$flags = $lintConfig['parse-tags'];
113+
}
114+
}
88115

89116
if ('github' === $this->format && !class_exists(GithubActionReporter::class)) {
90117
throw new \InvalidArgumentException('The "github" format is only available since "symfony/console" >= 5.3.');
@@ -95,8 +122,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
95122
$this->format = class_exists(GithubActionReporter::class) && GithubActionReporter::isGithubActionEnvironment() ? 'github' : 'txt';
96123
}
97124

125+
$flags = $flags ? Yaml::PARSE_CUSTOM_TAGS : 0;
126+
98127
$this->displayCorrectFiles = $output->isVerbose();
99-
$flags = $input->getOption('parse-tags') ? Yaml::PARSE_CUSTOM_TAGS : 0;
100128

101129
if (['-'] === $filenames) {
102130
return $this->display($io, [$this->validate(file_get_contents('php://stdin'), $flags)]);
@@ -113,7 +141,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
113141
}
114142

115143
foreach ($this->getFiles($filename) as $file) {
116-
$filesInfo[] = $this->validate(file_get_contents($file), $flags, $file);
144+
if (!\in_array($file->getPathname(), $excludes, true)) {
145+
$filesInfo[] = $this->validate(file_get_contents($file), $flags, $file);
146+
}
117147
}
118148
}
119149

@@ -266,4 +296,24 @@ private function isReadable(string $fileOrDirectory): bool
266296

267297
return $default($fileOrDirectory);
268298
}
299+
300+
private function parseLintConfig(string $config): array
301+
{
302+
if (!file_exists($config)) {
303+
throw new RuntimeException(sprintf('YAML Lint config "%s" not found.', $config));
304+
}
305+
306+
$result = (new Parser())
307+
->parseFile($config);
308+
309+
$allowedProperties = ['format', 'includes', 'excludes', 'parse-tags'];
310+
if (!is_array($result) || !empty(array_diff(array_keys($result), $allowedProperties))) {
311+
throw new RuntimeException(sprintf('Invalid YAML lint config "%s".', $config));
312+
}
313+
314+
$result['includes'] = $result['includes'] ?? [];
315+
$result['excludes'] = $result['excludes'] ?? [];
316+
317+
return $result;
318+
}
269319
}

src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,67 @@ public function testCustomTagsError()
142142
$this->assertSame(1, $ret, 'lint:yaml exits with code 1 in case of error');
143143
}
144144

145+
public function testLintWithExclude()
146+
{
147+
$tester = $this->createCommandTester();
148+
$filename = $this->createFile('foo: bar');
149+
150+
$ret = $tester->execute(['filename' => $filename, '--exclude' => [$filename]], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]);
151+
$this->assertSame(0, $ret, 'lint:yaml exits with code 0 in case of success');
152+
$this->assertStringContainsString('All 0 YAML files contain valid syntax.', trim($tester->getDisplay()));
153+
}
154+
155+
public function testMissingLintConfig()
156+
{
157+
$this->expectException(\RuntimeException::class);
158+
$this->createCommandTester()->execute(['--config' => 'missing.yml'], ['decorated' => false]);
159+
}
160+
161+
public function testInvalidLintConfig()
162+
{
163+
$this->expectException(\RuntimeException::class);
164+
$this->createCommandTester()->execute(['--config' => $this->createFile('foo: bar')], ['decorated' => false]);
165+
}
166+
167+
public function testCorrectLintConfig()
168+
{
169+
$tester = $this->createCommandTester();
170+
$filename = $this->createFile('foo: bar');
171+
172+
$yaml = <<<YAML
173+
parse-tags: false
174+
format: txt
175+
includes:
176+
- $filename
177+
excludes: []
178+
YAML;
179+
180+
$ret = $tester->execute(['--config' => $this->createFile($yaml)], ['decorated' => false]);
181+
182+
$this->assertSame(0, $ret, 'lint:yaml exits with code 0 in case of success');
183+
$this->assertStringContainsString('All 1 YAML files contain valid syntax.', trim($tester->getDisplay()));
184+
}
185+
186+
public function testMixedLintConfig()
187+
{
188+
$tester = $this->createCommandTester();
189+
$filename1 = $this->createFile('foo: bar');
190+
$filename2 = $this->createFile('foo: bar');
191+
192+
$yaml = <<<YAML
193+
parse-tags: false
194+
format: invalid
195+
includes:
196+
- $filename1
197+
excludes:
198+
- $filename1
199+
YAML;
200+
201+
$ret = $tester->execute(['filename' => [$filename2], '--format' => 'txt', '--exclude' => [$filename2], '--config' => $this->createFile($yaml)], ['decorated' => false]);
202+
$this->assertSame(0, $ret, 'lint:yaml exits with code 0 in case of success');
203+
$this->assertStringContainsString('All 0 YAML files contain valid syntax.', trim($tester->getDisplay()));
204+
}
205+
145206
public function testLintFileNotReadable()
146207
{
147208
$this->expectException(\RuntimeException::class);
@@ -166,7 +227,7 @@ protected function createCommandTester(): CommandTester
166227
{
167228
$application = new Application();
168229
$application->add(new LintCommand());
169-
$command = $application->find('lint:yaml');
230+
$command = $application->find(LintCommand::getDefaultName());
170231

171232
return new CommandTester($command);
172233
}

src/Symfony/Component/Yaml/composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
"symfony/polyfill-ctype": "~1.8"
2222
},
2323
"require-dev": {
24-
"symfony/console": "^4.4|^5.0"
24+
"symfony/console": "^5.3"
2525
},
2626
"conflict": {
27-
"symfony/console": "<4.4"
27+
"symfony/console": "<5.3"
2828
},
2929
"suggest": {
3030
"symfony/console": "For validating YAML files using the lint command"

0 commit comments

Comments
 (0)
0