Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.48% covered (success)
93.48%
43 / 46
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
PackageBuildConsoleCommand
93.33% covered (success)
93.33%
42 / 45
66.67% covered (warning)
66.67%
2 / 3
5.01
0.00% covered (danger)
0.00%
0 / 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%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 execute
90.91% covered (success)
90.91%
30 / 33
0.00% covered (danger)
0.00%
0 / 1
3.01
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Core\Packaging\Command;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use App\Core\Packaging\Dto\BuildConfigDto;
12use App\Core\Packaging\Service\PackageBuilderService;
13use Symfony\Component\Console\Command\Command;
14use Symfony\Component\Console\Input\InputInterface;
15use Symfony\Component\Console\Input\InputOption;
16use Symfony\Component\Console\Output\OutputInterface;
17use Symfony\Component\Console\Style\SymfonyStyle;
18use Throwable;
19
20/**
21 * Console Command for assembling stripped production release ZIP packages.
22 *
23 * @package App\Core\Packaging\Command
24 */
25final class PackageBuildConsoleCommand extends Command
26{
27    /**
28     * PackageBuildConsoleCommand constructor.
29     *
30     * @param string $basePath Application base directory path.
31     * @param PackageBuilderService|null $builder Optional custom builder instance.
32     */
33    public function __construct(
34        private readonly string $basePath,
35        private readonly ?PackageBuilderService $builder = null
36    ) {
37        parent::__construct('package:build');
38    }
39
40    /** {@inheritdoc} */
41    protected function configure(): void
42    {
43        $this->setDescription('Builds a stripped, production-ready release ZIP package (v0.0.1+).')
44            ->addOption(
45                'package-version',
46                's',
47                InputOption::VALUE_REQUIRED,
48                'Target package version (e.g. 0.0.1)',
49                '0.0.1'
50            )
51            ->addOption('type', 't', InputOption::VALUE_REQUIRED, 'Package type: full or update', 'full')
52            ->addOption('output', 'o', InputOption::VALUE_REQUIRED, 'Output directory path', 'build')
53            ->addOption('from-version', null, InputOption::VALUE_OPTIONAL, 'Base version for delta update package');
54    }
55
56    /** {@inheritdoc} */
57    protected function execute(InputInterface $input, OutputInterface $output): int
58    {
59        $io = new SymfonyStyle($input, $output);
60        $io->title('Ammonly Package Builder');
61
62        $version = (string) $input->getOption('package-version');
63        $type = (string) $input->getOption('type');
64        $outputDir = (string) $input->getOption('output');
65        $fromVersion = $input->getOption('from-version') !== null ? (string) $input->getOption('from-version') : null;
66
67        $config = new BuildConfigDto(
68            version: $version,
69            outputDir: $outputDir,
70            type: $type,
71            fromVersion: $fromVersion
72        );
73
74        $builder = $this->builder ?? new PackageBuilderService($this->basePath);
75
76        try {
77            $io->text(sprintf(
78                'Scanning repository and packaging version <info>%s</info> (type: %s)...',
79                $version,
80                $type
81            ));
82            $result = $builder->build($config);
83
84            $io->success(sprintf('Package successfully built: %s', $result['package_path']));
85            $io->table(
86                ['Metric', 'Value'],
87                [
88                    ['Version', $result['version']],
89                    ['Files Included', (string) $result['files_count']],
90                    ['Package Checksum (SHA-256)', $result['checksum']],
91                    ['Path', $result['package_path']],
92                ]
93            );
94
95            return Command::SUCCESS;
96        } catch (Throwable $e) {
97            $io->error('Failed to build package: ' . $e->getMessage());
98            return Command::FAILURE;
99        }
100    }
101}