Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
44 / 44
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
ChangelogPromoteCommand
100.00% covered (success)
100.00%
44 / 44
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%
21 / 21
100.00% covered (success)
100.00%
1 / 1
1
 execute
100.00% covered (success)
100.00%
22 / 22
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 FastForward\DevTools\Changelog\Manager\ChangelogManagerInterface;
25use FastForward\DevTools\Console\Input\HasJsonOption;
26use FastForward\DevTools\Filesystem\FilesystemInterface;
27use Psr\Clock\ClockInterface;
28use Psr\Log\LoggerInterface;
29use Symfony\Component\Console\Attribute\AsCommand;
30use Symfony\Component\Console\Command\Command;
31use Symfony\Component\Console\Input\InputArgument;
32use Symfony\Component\Console\Input\InputInterface;
33use Symfony\Component\Console\Input\InputOption;
34use Symfony\Component\Console\Output\OutputInterface;
35
36/**
37 * Promotes the Unreleased section into a published changelog version.
38 */
39#[AsCommand(
40    name: 'changelog:promote',
41    description: 'Promotes Unreleased entries into a published changelog version.'
42)]
43 class ChangelogPromoteCommand extends Command
44{
45    use HasJsonOption;
46    use LogsCommandResults;
47
48    /**
49     * @param FilesystemInterface $filesystem
50     * @param ChangelogManagerInterface $changelogManager
51     * @param ClockInterface $clock
52     * @param LoggerInterface $logger
53     */
54    public function __construct(
55        private  FilesystemInterface $filesystem,
56        private  ChangelogManagerInterface $changelogManager,
57        private  ClockInterface $clock,
58        private  LoggerInterface $logger,
59    ) {
60        parent::__construct();
61    }
62
63    /**
64     * Configures the promotion arguments and options.
65     */
66    protected function configure(): void
67    {
68        $this->setHelp(
69            'This command moves the current Unreleased entries into a released version section, records the'
70            . ' release date, and restores an empty Unreleased section.'
71        );
72
73        $this->addJsonOption()
74            ->addArgument(
75                name: 'version',
76                mode: InputArgument::REQUIRED,
77                description: 'The semantic version that should receive the current Unreleased entries.',
78            )
79            ->addOption(
80                name: 'date',
81                mode: InputOption::VALUE_REQUIRED,
82                description: 'The release date to record in YYYY-MM-DD format.',
83            )
84            ->addOption(
85                name: 'file',
86                mode: InputOption::VALUE_REQUIRED,
87                description: 'Path to the changelog file.',
88                default: 'CHANGELOG.md',
89            );
90    }
91
92    /**
93     * Promotes unreleased entries into the requested version section.
94     *
95     * @param InputInterface $input
96     * @param OutputInterface $output
97     */
98    protected function execute(InputInterface $input, OutputInterface $output): int
99    {
100        try {
101            $file = $this->filesystem->getAbsolutePath((string) $input->getOption('file'));
102            $version = (string) $input->getArgument('version');
103            $date = (string) ($input->getOption('date') ?: $this->clock->now()->format('Y-m-d'));
104
105            $this->changelogManager->promote($file, $version, $date);
106
107            return $this->success(
108                'Promoted Unreleased changelog entries to [{version}] in {absolute_file}.',
109                $input,
110                [
111                    'absolute_file' => $file,
112                    'version' => $version,
113                    'date' => $date,
114                ],
115            );
116        } catch (Throwable $throwable) {
117            return $this->failure(
118                'Unable to promote the changelog release.',
119                $input,
120                [
121                    'exception_message' => $throwable->getMessage(),
122                ],
123                (string) $input->getOption('file'),
124            );
125        }
126    }
127}