Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
39 / 39
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
ChangelogShowCommand
100.00% covered (success)
100.00%
39 / 39
100.00% covered (success)
100.00%
3 / 3
5
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 configure
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
1
 execute
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5/**
6 * Fast Forward Development Tools for PHP projects.
7 *
8 * This file is part of fast-forward/dev-tools project.
9 *
10 * @author   Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
11 * @license  https://opensource.org/licenses/MIT MIT License
12 *
13 * @see      https://github.com/php-fast-forward/
14 * @see      https://github.com/php-fast-forward/dev-tools
15 * @see      https://github.com/php-fast-forward/dev-tools/issues
16 * @see      https://php-fast-forward.github.io/dev-tools/
17 * @see      https://datatracker.ietf.org/doc/html/rfc2119
18 */
19
20namespace FastForward\DevTools\Console\Command;
21
22use FastForward\DevTools\Console\Command\Traits\LogsCommandResults;
23use Throwable;
24use Composer\Command\BaseCommand;
25use FastForward\DevTools\Changelog\Manager\ChangelogManagerInterface;
26use FastForward\DevTools\Console\Input\HasJsonOption;
27use FastForward\DevTools\Filesystem\FilesystemInterface;
28use Psr\Log\LoggerInterface;
29use Symfony\Component\Console\Attribute\AsCommand;
30use Symfony\Component\Console\Input\InputArgument;
31use Symfony\Component\Console\Input\InputInterface;
32use Symfony\Component\Console\Input\InputOption;
33use Symfony\Component\Console\Output\OutputInterface;
34
35/**
36 * Prints the rendered notes body for a released changelog version.
37 */
38#[AsCommand(
39    name: 'changelog:show',
40    description: 'Prints the notes body for a released changelog version.',
41    help: 'This command renders the body of one released changelog section so it can be reused for GitHub release notes.'
42)]
43 class ChangelogShowCommand extends BaseCommand implements LoggerAwareCommandInterface
44{
45    use HasJsonOption;
46    use LogsCommandResults;
47
48    /**
49     * @param FilesystemInterface $filesystem
50     * @param ChangelogManagerInterface $changelogManager
51     * @param LoggerInterface $logger
52     */
53    public function __construct(
54        private  FilesystemInterface $filesystem,
55        private  ChangelogManagerInterface $changelogManager,
56        private  LoggerInterface $logger,
57    ) {
58        parent::__construct();
59    }
60
61    /**
62     * Configures the show command arguments and options.
63     */
64    protected function configure(): void
65    {
66        $this->addJsonOption()
67            ->addArgument(
68                name: 'version',
69                mode: InputArgument::REQUIRED,
70                description: 'The released version to render.',
71            )
72            ->addOption(
73                name: 'file',
74                mode: InputOption::VALUE_REQUIRED,
75                description: 'Path to the changelog file.',
76                default: 'CHANGELOG.md',
77            );
78    }
79
80    /**
81     * Prints the rendered release notes body.
82     *
83     * @param InputInterface $input
84     * @param OutputInterface $output
85     */
86    protected function execute(InputInterface $input, OutputInterface $output): int
87    {
88        try {
89            $version = (string) $input->getArgument('version');
90            $file = (string) $input->getOption('file');
91            $releaseNotes = $this->changelogManager->renderReleaseNotes(
92                $this->filesystem->getAbsolutePath($file),
93                $version,
94            );
95
96            // This command feeds redirected release-notes files in changelog.yml,
97            // so plain-text mode MUST keep writing the rendered body directly.
98            if (! $this->isJsonOutput($input)) {
99                $output->write($releaseNotes);
100
101                return self::SUCCESS;
102            }
103
104            return $this->success(
105                $releaseNotes,
106                $input,
107                [
108                    'version' => $version,
109                    'release_notes' => $releaseNotes,
110                ],
111            );
112        } catch (Throwable $throwable) {
113            return $this->failure(
114                'Unable to render changelog release notes.',
115                $input,
116                [
117                    'exception_message' => $throwable->getMessage(),
118                ],
119                (string) $input->getOption('file'),
120            );
121        }
122    }
123}