Files
Orchestar/src/Service/Git/GitDeployment.php

155 lines
4.9 KiB
PHP

<?php
/*
* GitDeployment.php 2026-03-27 thomas
*
* Copyright (c) 2026 Thomas Schneider <thomas@inter-mundos.de>
* 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);
}
}