Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • composer/plugin/dorgflow
  • felixhaeberle/dorgflow
2 results
Show changes
Commits on Source (57)
ahoyapi: v2
commands:
dorgflow:
imports:
- ahoy.yml
usage: Dorgflow settings and updates
......@@ -12,6 +12,3 @@ indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{composer.json,composer.lock}]
indent_size = 4
vendor
composer.lock
/vendor/
/.env
/composer.lock
/.ahoy.l3d
/.ahoy.yml
include:
- project: 'gitlab-ci-cd/drupal'
ref: main
file: '/private-modules.yml'
ahoyapi: v2
commands:
update:
cmd: composer lakedrops:dorgflow "$@"
usage: Update DorgFlow setup in project
on:
cmd: |
DORGFLOW=1
echo "DORGFLOW=1" >>.env
env -i $(cat .env | xargs) >.env
composer lakedrops:dorgflow --no-interaction
usage: Turn on dorgflow
off:
cmd: |
DORGFLOW=0
echo "DORGFLOW=0" >>.env
env -i $(cat .env | xargs) >.env
composer lakedrops:dorgflow --no-interaction
usage: Turn off dorgflow
issue:
cmd: composer lakedrops:issuefork "$@" --no-interaction
usage: Load an issue fork for a specific project from drupal.org
{
"name": "lakedrops/dorgflow",
"description": "Composer Plugin for development environments",
"type": "composer-plugin",
"keywords": ["Development"],
"homepage": "https://gitlab.paragon-es.de/lakedrops/dorgflow",
"license": "GPL-2.0+",
"authors": [
{
"name": "Jürgen Haas",
"email": "juergen@paragon-es.de",
"homepage": "https://www.paragon-es.de",
"role": "Drupal Expert"
},
{
"name": "Richard Papp",
"email": "richard.papp@boromino.com",
"homepage": "http://www.boromino.com",
"role": "Drupal Expert"
}
],
"support": {
"issues": "https://gitlab.paragon-es.de/lakedrops/dorgflow/issues",
"source": "https://gitlab.paragon-es.de/lakedrops/dorgflow/tree/master"
"name": "lakedrops/dorgflow",
"description": "Composer Plugin for development environments",
"type": "composer-plugin",
"keywords": [
"Development"
],
"homepage": "https://gitlab.lakedrops.com/composer/plugin/dorgflow",
"license": "GPL-2.0-or-later",
"authors": [
{
"name": "Jürgen Haas",
"email": "juergen.haas@lakedrops.com",
"homepage": "https://www.lakedrops.com",
"role": "Drupal Expert"
},
"require": {
"composer-plugin-api": "^1.0.0",
"php": ">=5.4.5"
{
"name": "Daniel Speicher",
"email": "daniel.speicher@lakedrops.com",
"homepage": "https://www.lakedrops.com",
"role": "Drupal Expert"
},
"autoload": {
"psr-4": {
"LakeDrops\\DorgFlow\\": "src/"
}
},
"extra": {
"class": "LakeDrops\\DorgFlow\\Plugin"
},
"require-dev": {
"composer/composer": "dev-master",
"cypresslab/gitelephant": "~1.0",
"phpunit/phpunit": "^4.4.0"
{
"name": "Richard Papp",
"email": "richard.papp@lakedrops.com",
"homepage": "https://www.lakedrops.com",
"role": "Drupal Expert"
}
],
"support": {
"issues": "https://gitlab.lakedrops.com/composer/plugin/dorgflow/issues",
"source": "https://gitlab.lakedrops.com/composer/plugin/dorgflow/tree/main",
"docs": "https://devops-tools.docs.lakedrops.com/composer/plugin/dorgflow/"
},
"require": {
"php": ">=8.1",
"composer-plugin-api": "^2",
"cypresslab/gitelephant": "^2.0|^4.0",
"lakedrops/composer-json-utils": "^2.5||dev-develop"
},
"require-dev": {
"composer/composer": "^2",
"roave/security-advisories": "dev-latest"
},
"autoload": {
"psr-4": {
"LakeDrops\\DorgFlow\\": "src/"
}
},
"extra": {
"class": "LakeDrops\\DorgFlow\\Plugin"
}
}
parameters:
level: 6
checkMissingIterableValueType: false
checkGenericClassInNonGenericObjectType: false
treatPhpDocTypesAsCertain: false
<?php
namespace LakeDrops\DorgFlow;
use Composer\Plugin\Capability\CommandProvider as CommandProviderCapability;
/**
* Composer Command Provider for DorgFlow.
*
* @package LakeDrops\DorgFlow
*/
class CommandProvider implements CommandProviderCapability {
/**
* {@inheritdoc}
*/
public function getCommands(): array {
return [
new PrepareCommand(),
new IssueForkCommand(),
];
}
}
......@@ -2,98 +2,230 @@
namespace LakeDrops\DorgFlow;
use Composer\Package\PackageInterface;
use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\Script\Event as ScriptEvent;
use GitElephant\Repository;
use LakeDrops\Component\Composer\BaseHandler;
use Symfony\Component\Filesystem\Filesystem;
class Handler {
/**
* Handler class for the Dorgflow plugin.
*
* @package LakeDrops\DorgFlow
*/
class Handler extends BaseHandler {
/**
* @var \Composer\Composer
* {@inheritdoc}
*/
protected $composer;
public function configId(): string {
return 'dorgflow';
}
/**
* @var \Composer\IO\IOInterface
* {@inheritdoc}
*/
protected $io;
protected function configDefault(): array {
return [
'projects' => [],
'drupalspoons' => [],
];
}
/**
* Handler constructor.
*
* @param Composer $composer
* @param IOInterface $io
* Post install/update event to prepare projects for development.
*/
public function __construct(Composer $composer, IOInterface $io) {
$this->composer = $composer;
$this->io = $io;
public function prepareDevProjects(): void {
// We only do the fancy stuff for developers.
if (!$this->isDevMode() || $this->isCiContext()) {
return;
}
$this->init();
$dorgflow = $this->env->receiveGlobal('DORGFLOW', 'Dorgflow', '0');
if (empty($dorgflow)) {
return;
}
$installationManager = $this->composer->getInstallationManager();
foreach ([
'projects' => 'git.drupal.org:project',
'drupalspoons' => 'gitlab.com:drupalspoons',
'selfhosted' => FALSE,
] as $type => $url) {
if ($this->config->readValue($type) === NULL) {
continue;
}
if ($url === FALSE) {
$url = $this->config->readValue([$type, 'url']);
$projects = $this->config->readValue([$type, 'projects']);
$simpleMode = FALSE;
}
else {
$projects = $this->config->readValue($type);
$simpleMode = TRUE;
}
$this->io->write('Dorgflow: Preparing ' . $url . ' packages for development', TRUE);
foreach ($projects as $project => $specification) {
[, $projectname] = explode('/', $project);
if (!$simpleMode) {
$fullUrl = $url . ':' . $specification['path'];
$version = $specification['version'];
if (isset($specification['name'])) {
$projectname = $specification['name'];
}
}
else {
$fullUrl = $url;
$version = $specification;
}
$package = $this->getPackage($project);
if ($package === NULL) {
continue;
}
$path = $installationManager->getInstallPath($package);
$this->io->write("- $project => $path", TRUE);
$this->keepObjects($project);
$this->prepareWorkingDirectory($path, $projectname, $version, $fullUrl);
$this->restoreObjects($project);
}
}
}
/**
* Retrieve a package from the current composer process.
*
* @param string $name
* Name of the package to get from the current composer installation.
* Prepare the working directory of a git based package for dorgflow.
*
* @return PackageInterface
* @param string $path
* Name of the working directory.
* @param string $projectname
* Name of the project.
* @param string $version
* Version to checkout.
* @param string $url
* Base URL to checkout from.
*/
protected function getPackage($name) {
return $this->composer->getRepositoryManager()->getLocalRepository()->findPackage($name, '*');
protected function prepareWorkingDirectory(string $path, string $projectname, string $version, string $url): void {
$uri = 'git@' . $url . '/' . $projectname . '.git';
// Git Clone the repository into the working directory.
$repository = Repository::open($path);
$repository->init();
try {
$origin = $repository->getRemote('origin', FALSE);
if ($origin->getFetchURL() === $uri) {
// Already setup correctly.
return;
}
}
catch (\Exception $ex) {
// Ignore the exception and conitue setup.
}
$fs = new Filesystem();
$fs->remove($path);
$fs->mkdir($path);
$repository->init();
$repository->addRemote('origin', $uri);
$repository->fetch();
if ($repository->isDirty()) {
$this->io->write(' - directory dirty, can NOT checkout branch ' . $version, TRUE);
return;
}
$repository->checkout($version);
$repository->getCaller()->execute('branch --set-upstream-to origin/' . $version . ' ' . $version);
$this->io->write(' - completed', TRUE);
}
/**
* Post install/update event to prepare projects for development.
*
* @param ScriptEvent $event
* Load an issue fork for a specific project from drupal.org.
*/
public function prepareDevProjects($event) {
public function loadIssueFork(string $project, string $issue): void {
// We only do the fancy stuff for developers.
if (!$this->isDevMode() || $this->isCiContext()) {
return;
}
// We only do the fancy stuff for developers
if (!$event->isDevMode()) {
$this->init();
$dorgflow = $this->env->receiveGlobal('DORGFLOW', 'Dorgflow', '0');
if (empty($dorgflow)) {
$this->io->write('ERROR: Dorgflow is not enabled.', TRUE);
return;
}
$options = $this->getOptions();
$installationManager = $this->composer->getInstallationManager();
foreach ($options['projects'] as $project => $version) {
$package = $this->getPackage($project);
if (empty($package)) {
continue;
$package = $this->getPackage('drupal/' . $project);
if ($package === NULL) {
$this->io->write('ERROR: Project not installed.', TRUE);
return;
}
$path = $installationManager->getInstallPath($package);
if (!file_exists($path)) {
$this->io->write('ERROR: Installation path not found: ' . $path, TRUE);
return;
}
$projects = $this->config->readValue('projects');
if (empty($projects['drupal/' . $project])) {
$this->io->write('ERROR: Project not configured for dorgflow.', TRUE);
return;
}
if (!file_exists($path . '/.git')) {
$this->prepareDevProjects();
}
$uri = 'git@git.drupal.org:issue/' . $project . '-' . $issue . '.git';
$remote = $project . '-issue-' . $issue;
$repository = Repository::open($path);
try {
$origin = $repository->getRemote($remote, FALSE);
if ($origin->getFetchURL() === $uri) {
// Already setup correctly.
$this->io->write('Already available.');
return;
}
$path = $installationManager->getInstallPath($package);
$this->prepareWorkingDirectory($path, $project, $version, $options['username']);
}
catch (\Exception $ex) {
// Ignore the exception and conitue setup.
}
$repository->addRemote($remote, $uri);
$repository->fetch($remote);
$this->io->write('Successfully added issue fork.');
}
/**
* Retrieve excludes from optional "extra" configuration.
* Move files and directories to keep to the /tmp directory.
*
* @return array
* @param string $project
* The project name.
*/
protected function getOptions() {
$extra = $this->composer->getPackage()->getExtra() + ['dorgflow' => []];
$options = $extra['dorgflow'] + [
'projects' => [],
'username' => '',
];
return $options;
private function keepObjects(string $project): void {
if ($objects = $this->config->readValue(['keep', $project])) {
$fs = new Filesystem();
foreach ($objects as $id => $object) {
if (file_exists($object)) {
$this->io->write(' - keeping ' . $object);
$fs->rename($object, '/tmp/dorgflow-keep-' . $id, TRUE);
}
}
}
}
/**
* @inheritDoc
* Move files and directories to keep from the /tmp directory.
*
* @param string $project
* The project name.
*/
protected function prepareWorkingDirectory($path, $project, $version, $username) {
list(, $projectname) = explode('/', $project);
$repo = $username . '@git.drupal.org/project/' . $projectname . '.git';
// Git Clone the repository into the working directory
$repository = Repository::open($path);
$repository->cloneFrom($repo, '.');
$repository->checkout($version);
private function restoreObjects(string $project): void {
if ($objects = $this->config->readValue(['keep', $project])) {
$fs = new Filesystem();
foreach ($objects as $id => $object) {
if (file_exists('/tmp/dorgflow-keep-' . $id)) {
$this->io->write(' - restoring ' . $object);
$fs->rename('/tmp/dorgflow-keep-' . $id, $object, TRUE);
}
}
}
}
}
<?php
namespace LakeDrops\DorgFlow;
use LakeDrops\Component\Composer\BaseCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Composer Issue Fork Command for DorgFlow.
*
* @package LakeDrops\DorgFlow
*/
class IssueForkCommand extends BaseCommand {
/**
* {@inheritdoc}
*/
protected function configure(): void {
parent::configure();
$this
->setName('lakedrops:issuefork')
->addArgument('Project', InputArgument::REQUIRED, 'Name of the project, e.g. core')
->addArgument('Issue', InputArgument::REQUIRED, 'Number fo the issue')
->setDescription('Load an issue fork for a specific project from drupal.org.');
}
/**
* {@inheritdoc}
*/
public function getHandlerClass(): string {
return Handler::class;
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
parent::execute($input, $output);
/** @var Handler $handler */
$handler = $this->handler;
$handler->loadIssueFork($input->getArgument('Project'), $input->getArgument('Issue'));
return 0;
}
}
......@@ -2,46 +2,53 @@
namespace LakeDrops\DorgFlow;
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Plugin\Capability\CommandProvider as ComposerCommandProvider;
use Composer\Script\Event;
use Composer\Script\ScriptEvents;
use LakeDrops\Component\Composer\BasePlugin;
/**
* Composer plugin for preparing Drupal project for development with dorgflow.
*/
class Plugin implements PluginInterface, EventSubscriberInterface {
class Plugin extends BasePlugin {
/**
* @var \LakeDrops\DorgFlow\Handler
* {@inheritdoc}
*/
protected $handler;
public function getHandlerClass(): string {
return Handler::class;
}
/**
* {@inheritdoc}
*/
public function activate(Composer $composer, IOInterface $io) {
$this->handler = new Handler($composer, $io);
public function getCapabilities(): array {
return [
ComposerCommandProvider::class => CommandProvider::class,
];
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return array(
public static function getSubscribedEvents(): array {
return [
ScriptEvents::POST_INSTALL_CMD => 'prepareDevProjects',
ScriptEvents::POST_UPDATE_CMD => 'prepareDevProjects',
);
];
}
/**
* Post install/update event callback.
*
* @param \Composer\Script\Event $event
* The event that triggered the call of this function.
*/
public function prepareDevProjects($event) {
$this->handler->prepareDevProjects($event);
public function prepareDevProjects(Event $event): void {
/** @var \LakeDrops\DorgFlow\Handler $handler */
$handler = $this->handler;
$handler->setEvent($event);
$handler->prepareDevProjects();
}
}
<?php
namespace LakeDrops\DorgFlow;
use LakeDrops\Component\Composer\BaseCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Composer Prepare Command for DorgFlow.
*
* @package LakeDrops\DorgFlow
*/
class PrepareCommand extends BaseCommand {
/**
* {@inheritdoc}
*/
protected function configure(): void {
parent::configure();
$this
->setName('lakedrops:dorgflow')
->setDescription('Prepare drupal.org projects for dorgflow utility.');
}
/**
* {@inheritdoc}
*/
public function getHandlerClass(): string {
return Handler::class;
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
parent::execute($input, $output);
/** @var Handler $handler */
$handler = $this->handler;
$handler->prepareDevProjects();
return 0;
}
}