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 (38)
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'
# DorgFlow Composer Plugin
This is a composer plugin which prepares some of your projects in a composer base Drupal installation for drupal-org contributions powered by [Dorgflow](https://github.com/joachim-n/dorgflow).
You can keep your composer.json as is and only define the dev modules in the extra section such that this plugin can clone those projects for you from drupal.org so that you can immediately start using `dorgflow`.
Here is a sample of what to add to your composer.json:
```json
{
"extra": {
"dorgflow": {
"projects": {
"drupal/colorbox_field_formatter": "8.x-1.x",
"drupal/dimension": "8.x-1.x",
"drupal/drd": "8.x-3.x",
"drupal/drd_agent": "8.x-3.x"
}
}
}
}
```
Then, to get it to work, simply call `composer require lakedrops/dorgflow` and everything will be traken care off for you automatically - even if you update your Drupal project at any time in the future, the development environments for your defined projects will be kept in place and properly configured.
ahoyapi: v2
commands:
update:
cmd: composer dorgflow "$@"
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.lakedrops.com/composer/plugin/dorgflow",
"license": "GPL-2.0-or-later",
"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.lakedrops.com/composer/plugin/dorgflow/issues",
"source": "https://gitlab.lakedrops.com/composer/plugin/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",
"cypresslab/gitelephant": "~1.0",
"lakedrops/composer-json-utils": "^1.1.0",
"php": ">=5.6"
{
"name": "Daniel Speicher",
"email": "daniel.speicher@lakedrops.com",
"homepage": "https://www.lakedrops.com",
"role": "Drupal Expert"
},
"require-dev": {
"composer/composer": "^1.5.0",
"phpunit/phpunit": "^4.8.0"
},
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"LakeDrops\\DorgFlow\\": "src/"
}
},
"extra": {
"class": "LakeDrops\\DorgFlow\\Plugin",
"lakedrops": {
"scripts": {
"dorgflow": {
"callback": "LakeDrops\\DorgFlow\\Plugin::prepare",
"description": "Prepare drupal.org projects for dorgflow utility."
}
}
}
{
"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,76 +2,109 @@
namespace LakeDrops\DorgFlow;
use Composer\Script\Event;
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 {
/**
* Post install/update event to prepare projects for development.
*
* @param \Composer\Script\Event $event
* The event that triggered the call of this function.
* {@inheritdoc}
*/
public function prepareDevProjects(Event $event) {
public function configId(): string {
return 'dorgflow';
}
/**
* {@inheritdoc}
*/
protected function configDefault(): array {
return [
'projects' => [],
'drupalspoons' => [],
];
}
/**
* Post install/update event to prepare projects for development.
*/
public function prepareDevProjects(): void {
// We only do the fancy stuff for developers.
if (!$event->isDevMode()) {
if (!$this->isDevMode() || $this->isCiContext()) {
return;
}
$options = $this->getOptions();
if (empty($options['projects'])) {
$this->init();
$dorgflow = $this->env->receiveGlobal('DORGFLOW', 'Dorgflow', '0');
if (empty($dorgflow)) {
return;
}
$this->io->write('Dorgflow: Preparing drupol.org packages for development', TRUE);
$installationManager = $this->composer->getInstallationManager();
foreach ($options['projects'] as $project => $version) {
$package = $this->getPackage($project);
if (empty($package)) {
foreach ([
'projects' => 'git.drupal.org:project',
'drupalspoons' => 'gitlab.com:drupalspoons',
'selfhosted' => FALSE,
] as $type => $url) {
if ($this->config->readValue($type) === NULL) {
continue;
}
$path = $installationManager->getInstallPath($package);
$this->io->write("- $project => $path", TRUE);
$this->prepareWorkingDirectory($path, $project, $version);
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 options from composer.json "extra" configuration.
*
* @return array
* The options.
*/
protected function getOptions() {
$extra = $this->composer->getPackage()->getExtra() + ['dorgflow' => []];
return $extra['dorgflow'] + [
'projects' => [],
];
}
/**
* Prepare the working directory of a git based package for dorgflow.
*
* @param string $path
* Name of the working directory.
* @param string $project
* @param string $projectname
* Name of the project.
* @param string $version
* Version to checkout.
* @param string $url
* Base URL to checkout from.
*/
protected function prepareWorkingDirectory($path, $project, $version) {
list(, $projectname) = explode('/', $project);
$uri = 'git@git.drupal.org:project/' . $projectname . '.git';
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);
......@@ -79,7 +112,7 @@ class Handler extends BaseHandler {
try {
$origin = $repository->getRemote('origin', FALSE);
if ($origin && $origin->getFetchURL() == $uri) {
if ($origin->getFetchURL() === $uri) {
// Already setup correctly.
return;
}
......@@ -95,9 +128,104 @@ class Handler extends BaseHandler {
$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);
$this->io->write(' - completed', TRUE);
}
/**
* Load an issue fork for a specific project from drupal.org.
*/
public function loadIssueFork(string $project, string $issue): 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)) {
$this->io->write('ERROR: Dorgflow is not enabled.', TRUE);
return;
}
$installationManager = $this->composer->getInstallationManager();
$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;
}
}
catch (\Exception $ex) {
// Ignore the exception and conitue setup.
}
$repository->addRemote($remote, $uri);
$repository->fetch($remote);
$this->io->write('Successfully added issue fork.');
}
/**
* Move files and directories to keep to the /tmp directory.
*
* @param string $project
* The project name.
*/
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);
}
}
}
}
/**
* Move files and directories to keep from the /tmp directory.
*
* @param string $project
* The project name.
*/
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,6 +2,7 @@
namespace LakeDrops\DorgFlow;
use Composer\Plugin\Capability\CommandProvider as ComposerCommandProvider;
use Composer\Script\Event;
use Composer\Script\ScriptEvents;
use LakeDrops\Component\Composer\BasePlugin;
......@@ -14,39 +15,40 @@ class Plugin extends BasePlugin {
/**
* {@inheritdoc}
*/
public function getHandlerClass() {
public function getHandlerClass(): string {
return Handler::class;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return array(
ScriptEvents::POST_INSTALL_CMD => 'prepareDevProjects',
ScriptEvents::POST_UPDATE_CMD => 'prepareDevProjects',
);
public function getCapabilities(): array {
return [
ComposerCommandProvider::class => CommandProvider::class,
];
}
/**
* Post install/update event callback.
*
* @param \Composer\Script\Event $event
* The event that triggered the call of this function.
* {@inheritdoc}
*/
public function prepareDevProjects(Event $event) {
$this->handler->prepareDevProjects($event);
public static function getSubscribedEvents(): array {
return [
ScriptEvents::POST_INSTALL_CMD => 'prepareDevProjects',
ScriptEvents::POST_UPDATE_CMD => 'prepareDevProjects',
];
}
/**
* Script callback for putting in composer scripts to prepare the project.
* Post install/update event callback.
*
* @param \Composer\Script\Event $event
* The event that triggered the call of this function.
*/
public static function prepare(Event $event) {
$handler = new Handler($event->getComposer(), $event->getIO());
$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;
}
}