Completed
Push — master ( 4fe608...5ceeaf )
by Jindun
12s
created

AddEventCommand::askForProjectGroup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace TheAentMachine\AentGitLabCI\Command;
4
5
use TheAentMachine\AentGitLabCI\Aenthill\Metadata;
6
use TheAentMachine\AentGitLabCI\Exception\GitLabCIFileException;
7
use TheAentMachine\AentGitLabCI\Exception\JobException;
8
use TheAentMachine\AentGitLabCI\GitLabCI\GitLabCIFile;
9
use TheAentMachine\AentGitLabCI\GitLabCI\Job\Model\BranchesModel;
10
use TheAentMachine\Aenthill\CommonEvents;
11
use TheAentMachine\Aenthill\CommonMetadata;
12
use TheAentMachine\Aenthill\Manifest;
13
use TheAentMachine\Command\AbstractEventCommand;
14
use TheAentMachine\Exception\ManifestException;
15
use TheAentMachine\Exception\MissingEnvironmentVariableException;
16
use TheAentMachine\Question\CommonValidators;
17
18
final class AddEventCommand extends AbstractEventCommand
19
{
20
    protected function getEventName(): string
21
    {
22
        return CommonEvents::ADD_EVENT;
23
    }
24
25
    /**
26
     * @param null|string $payload
27
     * @return null|string
28
     * @throws GitLabCIFileException
29
     * @throws MissingEnvironmentVariableException
30
     */
31
    protected function executeEvent(?string $payload): ?string
32
    {
33
        $aentHelper = $this->getAentHelper();
34
        $aentHelper->title('Installing GitLab CI file');
35
36
        $file = new GitLabCIFile();
37
        if ($file->exist()) {
38
            $this->output->writeln('🦊 <info>' . GitLabCIFile::DEFAULT_FILENAME . '</info> found!');
39
        } else {
40
            $file->findOrCreate();
41
            $this->output->writeln('🦊 <info>' . GitLabCIFile::DEFAULT_FILENAME . '</info> was successfully created!');
42
        }
43
44
        $aentHelper->spacer();
45
46
        if (null === Manifest::getMetadata(Metadata::REGISTRY_DOMAIN_NAME_KEY)) {
47
            $registryDomainName = $this->askForRegistryDomainName();
48
            Manifest::addMetadata(Metadata::REGISTRY_DOMAIN_NAME_KEY, $registryDomainName);
49
        }
50
51
        if (null === Manifest::getMetadata(Metadata::PROJECT_GROUP_KEY)) {
52
            $projectGroup = $this->askForProjectGroup();
53
            Manifest::addMetadata(Metadata::PROJECT_GROUP_KEY, $projectGroup);
54
        }
55
56
        if (null === Manifest::getMetadata(Metadata::PROJECT_NAME_KEY)) {
57
            $projectName = $this->askForProjectName();
58
            Manifest::addMetadata(Metadata::PROJECT_NAME_KEY, $projectName);
59
        }
60
61
        if (null === Manifest::getMetadata(CommonMetadata::SINGLE_ENVIRONMENT_KEY)) {
62
            $branchesModel = $this->askForBranches((bool)$payload);
63
            Manifest::addMetadata(CommonMetadata::SINGLE_ENVIRONMENT_KEY, (string)!$branchesModel->isSingleBranch());
64
        }
65
66
        return Manifest::getMetadata(CommonMetadata::SINGLE_ENVIRONMENT_KEY);
67
    }
68
69
    private function askForRegistryDomainName(): string
70
    {
71
        return $this->getAentHelper()->question('Registry domain name')
72
            ->setHelpText('The domain name of the Docker Container Registry integrated with your Git repository on your GitLab. This is the space where your Docker images are stored.')
73
            ->compulsory()
74
            ->setValidator(CommonValidators::getDomainNameWithPortValidator())
75
            ->ask();
76
    }
77
78
    private function askForProjectGroup(): string
79
    {
80
        return $this->getAentHelper()->question('Project group')
81
            ->setHelpText('The group defined in the project path on GitLab. For example: for the project with URL "https://git.yourcompany.com/foo/bar", "foo" is the group name.')
82
            ->compulsory()
83
            ->setValidator(CommonValidators::getAlphaValidator(['-']))
84
            ->ask();
85
    }
86
87
    private function askForProjectName(): string
88
    {
89
        return $this->getAentHelper()->question('Project name')
90
            ->setHelpText('The project name defined in the project path on GitLab. For example: for the project with URL "https://git.yourcompany.com/foo/bar", "bar" is the project name.')
91
            ->compulsory()
92
            ->setValidator(CommonValidators::getAlphaValidator(['-']))
93
            ->ask();
94
    }
95
96
    private function askForBranches(bool $forSingleEnvironment = false): BranchesModel
97
    {
98
        try {
99
            $branchesModel = BranchesModel::newFromMetadata();
100
            return $branchesModel;
101
        } catch (ManifestException | JobException $e) {
102
            if ($forSingleEnvironment) {
103
                $branch = $this->askForBranch(true);
104
                return new BranchesModel([$branch], []);
105
            }
106
            $singleBranch = 'On one single branch';
107
            $allBranches = 'On all branches';
108
            $customBranches = 'Choose custom branches';
109
            $choices = [$singleBranch, $allBranches, $customBranches];
110
            $strategy = $this->getAentHelper()->choiceQuestion('Which deployment strategy to you want to apply?', $choices)
111
                ->ask();
112
113
            $branches = [];
114
            $branchesToIgnore = [];
115
            switch ($strategy) {
116
                case $singleBranch:
117
                    $branches[] = $this->askForBranch(true);
118
                    break;
119
                case $allBranches:
120
                    $branches[] = 'branches';
121
                    break;
122
                case $customBranches:
123
                    $branches[] = $this->askForBranch(true);
124
                    do {
125
                        $anotherBranch = $this->askForBranch(false);
126
                        if (!empty($anotherBranch)) {
127
                            $branches[] = $anotherBranch;
128
                        }
129
                    } while (!empty($anotherBranch));
130
                    break;
131
            }
132
133
            if ($strategy !== $singleBranch) {
134
                do {
135
                    $branchToIgnore = $this->getAentHelper()->question('Git branch to ignore (leave empty to skip)')
136
                        ->setDefault('')
137
                        ->setValidator(CommonValidators::getAlphaValidator(['_', '.', '-'], 'branch names can contain alphanumeric characters and "_", ".", "-".'))
138
                        ->ask();
139
                    if (!empty($branchToIgnore)) {
140
                        $branchesToIgnore[] = $branchToIgnore;
141
                    }
142
                } while (!empty($branchToIgnore));
143
            }
144
145
            $branchesModel = new BranchesModel($branches, $branchesToIgnore);
146
            $branchesModel->feedMetadata();
147
            return $branchesModel;
148
        }
149
    }
150
151
    private function askForBranch(bool $compulsory = true): string
152
    {
153
        $questionText = $compulsory ? 'Git branch' : 'Git branch (leave empty to skip)';
154
        $question = $this->getAentHelper()->question($questionText)
155
            ->setDefault('')
156
            ->setValidator(CommonValidators::getAlphaValidator(['_', '.', '-'], 'branch names can contain alphanumeric characters and "_", ".", "-".'));
157
        if ($compulsory) {
158
            $question->compulsory();
159
        }
160
        return $question->ask();
161
    }
162
}
163