Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.43% covered (success)
96.43%
27 / 28
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
ReleaseExportConsoleCommand
96.30% covered (success)
96.30%
26 / 27
66.67% covered (warning)
66.67%
2 / 3
8
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%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 execute
95.65% covered (success)
95.65%
22 / 23
0.00% covered (danger)
0.00%
0 / 1
6
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\Service\ReleaseExporterService;
12use Symfony\Component\Console\Command\Command;
13use Symfony\Component\Console\Input\InputInterface;
14use Symfony\Component\Console\Input\InputOption;
15use Symfony\Component\Console\Output\OutputInterface;
16use Symfony\Component\Console\Style\SymfonyStyle;
17use Throwable;
18
19/**
20 * Console Command for executing clean, zero-leak exports to distribution repositories.
21 *
22 * @package App\Core\Packaging\Command
23 */
24final class ReleaseExportConsoleCommand extends Command
25{
26    /**
27     * ReleaseExportConsoleCommand constructor.
28     *
29     * @param string                      $basePath Application base path.
30     * @param ReleaseExporterService|null $exporter Exporter service instance.
31     */
32    public function __construct(
33        private readonly string $basePath,
34        private readonly ?ReleaseExporterService $exporter = null
35    ) {
36        parent::__construct('release:export');
37    }
38
39    /** {@inheritdoc} */
40    protected function configure(): void
41    {
42        $this->setDescription('Safely exports filtered production files to distribution repository with auto-audit.')
43            ->addOption('target', 't', InputOption::VALUE_REQUIRED, 'Target directory path for export')
44            ->addOption('release-version', 's', InputOption::VALUE_OPTIONAL, 'Semantic version to set in target');
45    }
46
47    /** {@inheritdoc} */
48    protected function execute(InputInterface $input, OutputInterface $output): int
49    {
50        $io = new SymfonyStyle($input, $output);
51        $io->title('Ammonly Zero-Leak Release Exporter');
52
53        $target = (string) $input->getOption('target');
54        if ($target === '') {
55            $io->error('The --target option is mandatory. Please provide a destination repository path.');
56            return Command::INVALID;
57        }
58
59        $resolvedTarget = str_starts_with($target, '/') || preg_match('/^[A-Za-z]:[\\\\\/]/', $target)
60            ? $target
61            : $this->basePath . '/' . ltrim($target, '/\\');
62
63        $version = $input->getOption('release-version') !== null
64            ? (string) $input->getOption('release-version')
65            : null;
66
67        $io->text(sprintf('Exporting allowed codebase to: <info>%s</info>', $resolvedTarget));
68
69        $exporter = $this->exporter ?? new ReleaseExporterService($this->basePath);
70
71        try {
72            $report = $exporter->export($resolvedTarget, $version);
73
74            $io->success(sprintf(
75                'SUCCESS: Export completed and verified! %d files inspected with 0 violations.',
76                $report->scannedFilesCount
77            ));
78
79            return Command::SUCCESS;
80        } catch (Throwable $e) {
81            $io->error(sprintf('Export FAILED: %s', $e->getMessage()));
82            return Command::FAILURE;
83        }
84    }
85}