Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bard] various changes and updates #201

Merged
merged 4 commits into from
Dec 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions docs/bard/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,25 @@ Bard is used to manage monorepos.

## Usage

Initialize a new bard.json file
Initialize a new bard.json file for new monorepos.

```shell
bard init
```

Add repositories
### Adding Repositories

```shell
bard add path/to/code repoUrl
```

Push changes to read-only repos
### Push changes to read-only repos

```shell
bard push
```

Create a release
### Create a release

```shell
bard release major
Expand All @@ -37,7 +37,19 @@ bard release patch
Bard will track the versions so you can just use the keywords: major, minor,
patch.

### Copy files

Copy the LICENSE file from the root to all packages
```shell
bard copy LICENSE
```

### Merging `composer.json` files

When you have to maintain the composer.json files, this command will take the
packages and merge those into the main composer.json file. It will also update
the package's composer.json file with the correct values as well.

```shell
bard merge
```
3 changes: 2 additions & 1 deletion src/SonsOfPHP/Bard/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"php": ">=8.1",
"sonsofphp/event-dispatcher": "^0.3.x-dev",
"sonsofphp/json": "^0.3.x-dev",
"sonsofphp/logger": "^0.3.x-dev",
"sonsofphp/version": "^0.3.x-dev",
"symfony/console": "^4 || ^5 || ^6",
"symfony/dotenv": "^5 || ^6",
Expand Down Expand Up @@ -66,4 +67,4 @@
"url": "https://tidelift.com/subscription/pkg/packagist-sonsofphp-sonsofphp"
}
]
}
}
42 changes: 35 additions & 7 deletions src/SonsOfPHP/Bard/src/Console/Command/AddCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,37 +24,65 @@ protected function configure(): void
$this
->setDescription('Add new repo')
->addOption('branch', null, InputOption::VALUE_REQUIRED, 'What branch we working with?', 'main')
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Dry Run (Do not make any changes)')
->addArgument('path', InputArgument::REQUIRED, 'Path where code will be')
->addArgument('repository', InputArgument::REQUIRED, 'Repository')
->addArgument('repository', InputArgument::REQUIRED, 'Repository Uri')
->setHelp(
<<<'HELP'
The <info>add</info> command will add additional repositories that need to be managed
into the `bard.json` file.

Examples:

<comment>%command.full_name% src/SonsOfPHP/Bard git@github.com:vendor/package.git</comment>

Read more at https://docs.sonsofphp.com/bard/
HELP
)
;
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$bardConfig = new JsonFile($input->getOption('working-dir') . '/bard.json');
$formatter = $this->getHelper('formatter');
$io = new SymfonyStyle($input, $output);
$isDryRun = $input->getOption('dry-run');

// ---
if (null === $packages = $bardConfig->getSection('packages')) {
$packages = [];
}

// @todo Check to make sure this package does not already exist
foreach ($packages as $pkg) {
if ($pkg['path'] === $input->getArgument('path')) {
$io->error([
sprintf('It appears that the path "%s" is currently being used.', $pkg['path']),
'Please check your bard.json file',
]);
return self::FAILURE;
}
}
$packages[] = [
'path' => $input->getArgument('path'),
'path' => $input->getArgument('path'),
'repository' => $input->getArgument('repository'),
];
// ---

$bardConfig = $bardConfig->setSection('packages', $packages);
$commands = [
['git', 'subtree', 'add', '--prefix', $input->getArgument('path'), $input->getArgument('repository'), $input->getOption('branch'), '--squash'],
];
foreach ($commands as $cmd) {
$process = new Process($cmd);
$io->text($process->getCommandLine());
$this->getHelper('process')->mustRun($output, $process, sprintf('There was and error running command: %s', $process->getCommandLine()));
if (!$isDryRun) {
$this->getHelper('process')->mustRun($output, $process, sprintf('There was and error running command: %s', $process->getCommandLine()));
}
}

if (!$isDryRun) {
file_put_contents($bardConfig->getFilename(), $bardConfig->toJson());
}

file_put_contents($bardConfig->getFilename(), $bardConfig->toJson());
$io->success('Package has been added.');

return self::SUCCESS;
Expand Down
38 changes: 35 additions & 3 deletions src/SonsOfPHP/Bard/src/Console/Command/CopyCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use SonsOfPHP\Bard\JsonFile;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Process\Process;
Expand All @@ -22,25 +23,56 @@ protected function configure(): void
{
$this
->setDescription('Copies a file to each package')
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Dry Run (Do not make any changes)')
->addArgument('source', InputArgument::REQUIRED, 'Source file to copy')
->addArgument('package', InputArgument::OPTIONAL, 'Which package?')
->setHelp(
<<<'HELP'
The <info>copy</info> command will copy whatever file you give it to all the other
repositories it is managing. This is useful for LICENSE files.

Examples:

<comment>%command.full_name% LICENSE</comment>

Read more at https://docs.sonsofphp.com/bard/
HELP
)
;
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$io = new SymfonyStyle($input, $output);
$isDryRun = $input->getOption('dry-run');

// ---
$sourceFile = $input->getOption('working-dir') . '/' . $input->getArgument('source');
if (!is_file($sourceFile)) {
throw new \RuntimeException(sprintf('The file "%s" is an invalid file.', $sourceFile));
}
// ---

// ---
$bardJsonFile = new JsonFile($input->getOption('working-dir') . '/bard.json');
foreach ($bardJsonFile->getSection('packages') as $pkg) {
$pkgComposerFile = realpath($input->getOption('working-dir') . '/' . $pkg['path'] . '/composer.json');
$pkgComposerJsonFile = new JsonFile($pkgComposerFile);
$pkgName = $pkgComposerJsonFile->getSection('name');

if (null !== $input->getArgument('package') && $pkgName !== $input->getArgument('package')) {
continue;
}

$process = new Process(['cp', $sourceFile, $pkg['path']]);
$io->text($process->getCommandLine());
$this->getHelper('process')->run($output, $process);
if (!$isDryRun) {
$this->getHelper('process')->run($output, $process);
}
}
// ---

$io->success('File has been copied.');
$io->success(sprintf('File "%s" has been copied to all managed repos.', $sourceFile));

return self::SUCCESS;
}
Expand Down
13 changes: 4 additions & 9 deletions src/SonsOfPHP/Bard/src/Console/Command/InitCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use SonsOfPHP\Bard\JsonFile;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
* Creates the initial bard.json file.
Expand All @@ -17,26 +18,20 @@ final class InitCommand extends AbstractCommand
{
protected static $defaultName = 'init';

// public function __construct()
// {
// parent::__construct();
// }

protected function configure(): void
{
$this
->setDescription('Creates the initial bard.json file')
;
}

protected function initialize(InputInterface $input, OutputInterface $output): void {}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$filename = $input->getOption('working-dir') . '/bard.json';

if (file_exists($filename)) {
$output->writeln('bard.json file already exists');
$io->error(sprintf('%s/bard.json file already exists', $input->getOption('working-dir')));

return self::FAILURE;
}
Expand All @@ -51,7 +46,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
['path' => 'packages/component', 'repository' => 'git@github.com/org/component'],
]);

$output->writeln($bardJsonFile->toJson());
$io->text($bardJsonFile->toJson());

file_put_contents($bardJsonFile->getFilename(), $bardJsonFile->toJson());

Expand Down
31 changes: 24 additions & 7 deletions src/SonsOfPHP/Bard/src/Console/Command/MergeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
use SonsOfPHP\Bard\Worker\File\Composer\Root\UpdateRequireDevSection;
use SonsOfPHP\Bard\Worker\File\Composer\Root\UpdateRequireSection;
use SonsOfPHP\Component\Json\Json;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
* Merges composer.json files.
Expand All @@ -42,8 +45,9 @@ public function __construct()
protected function configure(): void
{
$this
// options for dry-run, by default it should be a dry-run
->setDescription('Merges package composer.json files into main composer.json file')
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Dry Run (Do not make any changes)')
->addArgument('package', InputArgument::OPTIONAL, 'Which package?')
;
}

Expand All @@ -66,6 +70,9 @@ protected function initialize(InputInterface $input, OutputInterface $output): v

protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$isDryRun = $input->getOption('dry-run');

$this->formatter = $this->getHelper('formatter');

$rootComposerJsonFile = new JsonFile($input->getOption('working-dir') . '/composer.json');
Expand All @@ -75,13 +82,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$rootComposerJsonFile = $rootComposerJsonFile->setSection('autoload-dev', []);

foreach ($this->bardConfig['packages'] as $pkg) {
$packageComposerFile = realpath($input->getOption('working-dir') . '/' . $pkg['path'] . '/composer.json');
if (!file_exists($packageComposerFile)) {
$pkgComposerFile = realpath($input->getOption('working-dir') . '/' . $pkg['path'] . '/composer.json');
if (!file_exists($pkgComposerFile)) {
$output->writeln(sprintf('No "%s" found, skipping', $packageComposerFile));
continue;
}

$pkgComposerJsonFile = new JsonFile(realpath($input->getOption('working-dir') . '/' . $pkg['path'] . '/composer.json'));
$pkgComposerJsonFile = new JsonFile($pkgComposerFile);
$pkgName = $pkgComposerJsonFile->getSection('name');
if (null !== $input->getArgument('package') && $pkgName !== $input->getArgument('package')) {
continue;
}

$output->writeln($this->formatter->formatSection('bard', sprintf('Merging "%s" into root composer.json', $pkgComposerJsonFile->getSection('name'))));

Expand All @@ -100,12 +111,18 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$pkgComposerJsonFile = $pkgComposerJsonFile->with(new Authors($rootComposerJsonFile));
$pkgComposerJsonFile = $pkgComposerJsonFile->with(new Funding($rootComposerJsonFile));

file_put_contents($pkgComposerJsonFile->getFilename(), $pkgComposerJsonFile->toJson());
if (!$isDryRun) {
file_put_contents($pkgComposerJsonFile->getFilename(), $pkgComposerJsonFile->toJson());
$io->text(sprintf('Updated "%s"', $pkgComposerJsonFile->getFilename()));
}
}

file_put_contents($rootComposerJsonFile->getFilename(), $rootComposerJsonFile->toJson());
if (!$isDryRun) {
file_put_contents($rootComposerJsonFile->getFilename(), $rootComposerJsonFile->toJson());
$io->text(sprintf('Updated "%s"', $rootComposerJsonFile->getFilename()));
}

$output->writeln('complete');
$io->success('Merge Complete');

return self::SUCCESS;
}
Expand Down
19 changes: 14 additions & 5 deletions src/SonsOfPHP/Bard/src/Console/Command/PushCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace SonsOfPHP\Bard\Console\Command;

use SonsOfPHP\Bard\JsonFile;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
Expand All @@ -25,32 +26,40 @@ protected function configure(): void
$this
->setDescription('Push changes to package repos using git subtree push')
->addOption('branch', null, InputOption::VALUE_REQUIRED, 'What branch we working with?', 'main')
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Dry Run (Do not make any changes)')
->addArgument('package', InputArgument::OPTIONAL, 'Which package do you want to push?')
;
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$bardConfig = new JsonFile($input->getOption('working-dir') . '/bard.json');
$formatter = $this->getHelper('formatter');
$io = new SymfonyStyle($input, $output);
$isDryRun = $input->getOption('dry-run');

foreach ($bardConfig->getSection('packages') as $pkg) {
$pkgComposerFile = realpath($input->getOption('working-dir') . '/' . $pkg['path'] . '/composer.json');
$pkgComposerJsonFile = new JsonFile($pkgComposerFile);
$pkgName = $pkgComposerJsonFile->getSection('name');
$io->text(sprintf('Pushing <info>%s</>', $pkgName));

if (null !== $input->getArgument('package') && $pkgName !== $input->getArgument('package')) {
continue;
}

$commands = [
// subtree push
['git', 'subtree', 'push', '-P', $pkg['path'], $pkg['repository'], $input->getOption('branch')],
];

$io->text(sprintf('Pushing <info>%s</>', $pkgName));
foreach ($commands as $cmd) {
$process = new Process($cmd);
$io->text($process->getCommandLine());
$this->getHelper('process')
->mustRun($output, $process, sprintf('There was and error running command: %s', $process->getCommandLine()))
->wait();
if (!$isDryRun) {
$this->getHelper('process')
->mustRun($output, $process, sprintf('There was and error running command: %s', $process->getCommandLine()))
->wait();
}
}
}

Expand Down
Loading
Loading