* Alle Rechte vorbehalten. */ namespace App\Service\Git; use App\Entity\Project; use App\Service\Deployment\DeploymentService; use App\Service\ProjectConfigDirService; use App\Traits\LoggerTrait; use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; #[AutoconfigureTag('app.deployment_service', ['git'])] class GitDeployment extends DeploymentService { use LoggerTrait; const string GIT_DIR = 'repo.git'; public function __construct( protected GitService $git, private readonly ProjectConfigDirService $projectConfigDirService, ){} public function supports(): string { return 'git'; } public function init(Project $project): void { $this->git->setWorkingDir($project->projectDir); } /** * Handles the deployment process for the specified project by fetching the required * resources and deploying the appropriate version. * * This method first fetches the necessary project resources. Then, it delegates * the deployment process to the deployment method, optionally using the provided * version and step parameters. * * @param Project $project The project to handle. * @param string $version An optional specific version to deploy. Defaults to an empty string. * @param string $step An optional step parameter used during the handling process. Defaults to an empty string. * * @return void */ public function handle(Project $project, string $version = '', string $step = ''): void { $this->fetch($project); $this->deploy($project, $version); } /** * Fetches the latest updates for the specified project's repository. * Depending on the state of the repository directory, either a fetch or * a full clone operation is performed. Supports authenticated access to * repositories when a URL with HTTP is provided. * * If the repository is already cloned, this method performs a fetch operation * to synchronize the local repository. Otherwise, it clones the repository in * mirror mode to the designated directory. * * During the process, the deployment step is updated to reflect the current * stage of the fetch operation for the given project. * * @param Project $project The project whose repository updates are to be fetched. * * @return void */ public function fetch(Project $project): void { $this->projectConfigDirService->setDeploymentStep($project->projectDir, 'fetch'); $options = []; if(!empty($project->deployment['repository_url']) && str_starts_with($project->deployment['repository_url'], 'http')) { $options['auth_basic'] = [ 'username' => $project->deployment['username'] ?? '', 'password' => $project->deployment['password'] ?? '', ]; } if($this->git->isCloned(self::GIT_DIR)) { $this->projectConfigDirService->setDeploymentStep($project->projectDir, 'fetch.git.clone'); $this->git->fetchRepo( dir: self::GIT_DIR, options: $options, ); } else { $this->projectConfigDirService->setDeploymentStep($project->projectDir, 'fetch.git.fetch'); $this->git->cloneRepo( repoUrl: $project->deployment['repository_url'], targetDir: self::GIT_DIR, options: [...$options, '--mirror'], ); } } /** * Deploys the specified project by preparing a clean working directory, * cloning the git repository, and checking out the appropriate version. * * If the version is set to "default", it translates to the current state of * the default branch in the repository. If set to "latest" or if no version * is provided, the latest release of the repository is checked out. * * @param Project $project The project to be deployed. * @param string $version The version to be deployed, which could be explicit, "default", or "latest". * * @return void */ public function deploy(Project $project, string $version): void { # remove work tree $this->clearDeploymentFiles($project); # create work tree $this->git->cloneRepo(self::GIT_DIR, $this->filesDir); // default translates to current state of default branch if($version === 'default') { $version = $this->git->getRepoDefaultBranch(self::GIT_DIR); } if(!$version || $version === 'latest') { # check out latest release $this->git->checkoutLatestRelease($this->filesDir); } else { $this->git->checkoutRepo($this->filesDir, $version); } parent::deploy($project, $version); } }