155 lines
4.9 KiB
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);
|
|
}
|
|
}
|