Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dc33317

Browse filesBrowse files
committed
[TwigBridge] LintCommand supports Github Actions annotations
1 parent c01b032 commit dc33317
Copy full SHA for dc33317

File tree

2 files changed

+74
-5
lines changed
Filter options

2 files changed

+74
-5
lines changed

‎src/Symfony/Bridge/Twig/Command/LintCommand.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Twig/Command/LintCommand.php
+26-5Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Bridge\Twig\Command;
1313

14+
use Symfony\Component\Console\CI\GithubActionReporter;
1415
use Symfony\Component\Console\Command\Command;
1516
use Symfony\Component\Console\Exception\InvalidArgumentException;
1617
use Symfony\Component\Console\Exception\RuntimeException;
@@ -37,6 +38,10 @@ class LintCommand extends Command
3738
protected static $defaultName = 'lint:twig';
3839

3940
private $twig;
41+
/**
42+
* @var string
43+
*/
44+
private $format;
4045

4146
public function __construct(Environment $twig)
4247
{
@@ -49,7 +54,7 @@ protected function configure()
4954
{
5055
$this
5156
->setDescription('Lints a template and outputs encountered errors')
52-
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
57+
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format')
5358
->addOption('show-deprecations', null, InputOption::VALUE_NONE, 'Show deprecations as errors')
5459
->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')
5560
->setHelp(<<<'EOF'
@@ -79,6 +84,15 @@ protected function execute(InputInterface $input, OutputInterface $output)
7984
$io = new SymfonyStyle($input, $output);
8085
$filenames = $input->getArgument('filename');
8186
$showDeprecations = $input->getOption('show-deprecations');
87+
$this->format = $input->getOption('format');
88+
89+
if ('github' === $this->format && !class_exists(GithubActionReporter::class)) {
90+
throw new \InvalidArgumentException('The "github" format is only available since "symfony/console" >= 5.3.');
91+
}
92+
93+
if (null === $this->format) {
94+
$this->format = class_exists(GithubActionReporter::class) && GithubActionReporter::isGithubActionEnvironment() ? 'github' : 'txt';
95+
}
8296

8397
if (['-'] === $filenames) {
8498
return $this->display($input, $output, $io, [$this->validate(file_get_contents('php://stdin'), uniqid('sf_', true))]);
@@ -168,26 +182,29 @@ private function validate(string $template, string $file): array
168182

169183
private function display(InputInterface $input, OutputInterface $output, SymfonyStyle $io, array $files)
170184
{
171-
switch ($input->getOption('format')) {
185+
switch ($this->format) {
172186
case 'txt':
173187
return $this->displayTxt($output, $io, $files);
174188
case 'json':
175189
return $this->displayJson($output, $files);
190+
case 'github':
191+
return $this->displayTxt($output, $io, $files, true);
176192
default:
177193
throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format')));
178194
}
179195
}
180196

181-
private function displayTxt(OutputInterface $output, SymfonyStyle $io, array $filesInfo)
197+
private function displayTxt(OutputInterface $output, SymfonyStyle $io, array $filesInfo, bool $errorAsGithubAnnotations = false)
182198
{
183199
$errors = 0;
200+
$githubReporter = $errorAsGithubAnnotations ? new GithubActionReporter($output) : null;
184201

185202
foreach ($filesInfo as $info) {
186203
if ($info['valid'] && $output->isVerbose()) {
187204
$io->comment('<info>OK</info>'.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
188205
} elseif (!$info['valid']) {
189206
++$errors;
190-
$this->renderException($io, $info['template'], $info['exception'], $info['file']);
207+
$this->renderException($io, $info['template'], $info['exception'], $info['file'], $githubReporter);
191208
}
192209
}
193210

@@ -219,10 +236,14 @@ private function displayJson(OutputInterface $output, array $filesInfo)
219236
return min($errors, 1);
220237
}
221238

222-
private function renderException(OutputInterface $output, string $template, Error $exception, string $file = null)
239+
private function renderException(OutputInterface $output, string $template, Error $exception, string $file = null, ?GithubActionReporter $githubReporter = null)
223240
{
224241
$line = $exception->getTemplateLine();
225242

243+
if ($githubReporter) {
244+
$githubReporter->error($exception->getRawMessage(), $file, $line);
245+
}
246+
226247
if ($file) {
227248
$output->text(sprintf('<error> ERROR </error> in %s (line %s)', $file, $line));
228249
} else {

‎src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php
+48Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Bridge\Twig\Command\LintCommand;
1616
use Symfony\Component\Console\Application;
17+
use Symfony\Component\Console\CI\GithubActionReporter;
1718
use Symfony\Component\Console\Output\OutputInterface;
1819
use Symfony\Component\Console\Tester\CommandTester;
1920
use Twig\Environment;
@@ -107,6 +108,53 @@ public function testLintDefaultPaths()
107108
self::assertStringContainsString('OK in', trim($tester->getDisplay()));
108109
}
109110

111+
public function testLintIncorrectFileWithGithubFormat()
112+
{
113+
if (!class_exists(GithubActionReporter::class)) {
114+
$this->expectException(\InvalidArgumentException::class);
115+
$this->expectExceptionMessage('The "github" format is only available since "symfony/console" >= 5.3');
116+
}
117+
118+
$filename = $this->createFile('{{ foo');
119+
$tester = $this->createCommandTester();
120+
121+
$tester->execute(['filename' => [$filename], '--format' => 'github'], ['decorated' => false]);
122+
123+
if (!class_exists(GithubActionReporter::class)) {
124+
return;
125+
}
126+
127+
self::assertEquals(1, $tester->getStatusCode(), 'Returns 1 in case of error');
128+
self::assertStringMatchesFormat('%A::error file=%s, line=1, col=0::Unexpected token "end of template" ("end of print statement" expected).%A', trim($tester->getDisplay()));
129+
}
130+
131+
public function testLintAutodetectsGithubActionEnvironment()
132+
{
133+
if (!class_exists(GithubActionReporter::class)) {
134+
$this->markTestSkipped('The "github" format is only available since "symfony/console" >= 5.3.');
135+
}
136+
137+
$prev = getenv('GITHUB_ACTIONS');
138+
putenv('GITHUB_ACTIONS');
139+
140+
try {
141+
putenv('GITHUB_ACTIONS=1');
142+
143+
$filename = $this->createFile('{{ foo');
144+
$tester = $this->createCommandTester();
145+
146+
$tester->execute(['filename' => [$filename]], ['decorated' => false]);
147+
148+
if (!class_exists(GithubActionReporter::class)) {
149+
return;
150+
}
151+
152+
self::assertStringMatchesFormat('%A::error file=%s, line=1, col=0::Unexpected token "end of template" ("end of print statement" expected).%A', trim($tester->getDisplay()));
153+
} finally {
154+
putenv('GITHUB_ACTIONS'.($prev ? "=$prev" : ''));
155+
}
156+
}
157+
110158
private function createCommandTester(): CommandTester
111159
{
112160
$environment = new Environment(new FilesystemLoader(\dirname(__DIR__).'/Fixtures/templates/'));

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.