Skip to content

Commit

Permalink
Merge pull request #230 from ghostwriter/feature/support-running-auto…
Browse files Browse the repository at this point in the history
…matic-releases-actions-after-failure

Re-running automatic releases actions after failure
  • Loading branch information
Ocramius committed Jan 5, 2023
2 parents 3589c9f + 1a77168 commit 12dde9b
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 13 deletions.
3 changes: 2 additions & 1 deletion bin/console.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use Laminas\AutomaticReleases\Git\CreateTagViaConsole;
use Laminas\AutomaticReleases\Git\FetchAndSetCurrentUserByReplacingCurrentOriginRemote;
use Laminas\AutomaticReleases\Git\GetMergeTargetCandidateBranchesFromRemoteBranches;
use Laminas\AutomaticReleases\Git\HasTagViaConsole;
use Laminas\AutomaticReleases\Git\PushViaConsole;
use Laminas\AutomaticReleases\Github\Api\GraphQL\Query\GetMilestoneFirst100IssuesAndPullRequests;
use Laminas\AutomaticReleases\Github\Api\GraphQL\RunGraphQLQuery;
Expand Down Expand Up @@ -127,7 +128,7 @@ static function (int $errorCode, string $message = '', string $file = '', int $l
$getMilestone,
$commitChangelog,
$createReleaseText,
new CreateTagViaConsole(),
new CreateTagViaConsole(new HasTagViaConsole(), $logger),
$push,
$createRelease,
),
Expand Down
5 changes: 4 additions & 1 deletion src/Git/CreateTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@

interface CreateTag
{
/** @param non-empty-string $repositoryDirectory */
/**
* @param non-empty-string $repositoryDirectory
* @param non-empty-string $tagName
*/
public function __invoke(
string $repositoryDirectory,
BranchName $sourceBranch,
Expand Down
24 changes: 23 additions & 1 deletion src/Git/CreateTagViaConsole.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,43 @@
use Psl\File;
use Psl\Filesystem;
use Psl\Shell;
use Psr\Log\LoggerInterface;

use function sprintf;

final class CreateTagViaConsole implements CreateTag
{
public function __construct(
private readonly HasTag $hasTag,
private readonly LoggerInterface $logger,
) {
}

public function __invoke(
string $repositoryDirectory,
BranchName $sourceBranch,
string $tagName,
string $changelog,
SecretKeyId $keyId,
): void {
if (($this->hasTag)($repositoryDirectory, $tagName)) {
$this->logger->info(
sprintf('[CreateTagViaConsole] Skipping this step; tag "%s" already exists.', $tagName),
);

return;
}

$tagFileName = Filesystem\create_temporary_file(Env\temp_dir(), 'created_tag');

File\write($tagFileName, $changelog);

Shell\execute('git', ['checkout', $sourceBranch->name()], $repositoryDirectory);
Shell\execute('git', ['tag', $tagName, '-F', $tagFileName, '--cleanup=whitespace', '--local-user=' . $keyId->id()], $repositoryDirectory);

Shell\execute(
'git',
['tag', $tagName, '-F', $tagFileName, '--cleanup=whitespace', '--local-user=' . $keyId->id()],
$repositoryDirectory,
);
}
}
17 changes: 17 additions & 0 deletions src/Git/HasTag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Laminas\AutomaticReleases\Git;

interface HasTag
{
/**
* @param non-empty-string $repositoryDirectory
* @param non-empty-string $tagName
*/
public function __invoke(
string $repositoryDirectory,
string $tagName,
): bool;
}
24 changes: 24 additions & 0 deletions src/Git/HasTagViaConsole.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Laminas\AutomaticReleases\Git;

use Psl\Shell;

use function str_contains;
use function trim;

final class HasTagViaConsole implements HasTag
{
public function __invoke(string $repositoryDirectory, string $tagName): bool
{
$output = Shell\execute('git', ['tag', '--list', $tagName], $repositoryDirectory);

if (trim($output) === '') {
return false;
}

return str_contains($output, $tagName);
}
}
71 changes: 61 additions & 10 deletions test/unit/Git/CreateTagViaConsoleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
namespace Laminas\AutomaticReleases\Test\Unit\Git;

use Laminas\AutomaticReleases\Git\CreateTagViaConsole;
use Laminas\AutomaticReleases\Git\HasTag;
use Laminas\AutomaticReleases\Git\HasTagViaConsole;
use Laminas\AutomaticReleases\Git\Value\BranchName;
use Laminas\AutomaticReleases\Gpg\ImportGpgKeyFromStringViaTemporaryFile;
use Laminas\AutomaticReleases\Gpg\SecretKeyId;
Expand All @@ -13,8 +15,10 @@
use Psl\Filesystem;
use Psl\Shell;
use Psr\Http\Message\UriInterface;
use Psr\Log\LoggerInterface;

use function Psl\File\read;
use function sprintf;

/** @covers \Laminas\AutomaticReleases\Git\CreateTagViaConsole */
final class CreateTagViaConsoleTest extends TestCase
Expand Down Expand Up @@ -46,19 +50,24 @@ protected function setUp(): void

public function testCreatesSignedTag(): void
{
$logger = $this->createMock(LoggerInterface::class);
$logger->expects(self::never())->method('info');

$sourceUri = $this->createMock(UriInterface::class);
$sourceUri->method('__toString')->willReturn($this->repository);

$sourceUri->method('__toString')
->willReturn($this->repository);
$hasTag = $this->createMock(HasTag::class);
$hasTag->method('__invoke')
->with($this->repository, 'name-of-the-tag')
->willReturn(false);

(new CreateTagViaConsole())
->__invoke(
$this->repository,
BranchName::fromName('tag-branch'),
'name-of-the-tag',
'changelog text for the tag',
$this->key,
);
(new CreateTagViaConsole($hasTag, $logger))(
$this->repository,
BranchName::fromName('tag-branch'),
'name-of-the-tag',
'changelog text for the tag',
$this->key,
);

Shell\execute('git', ['tag', '-v', 'name-of-the-tag'], $this->repository);

Expand All @@ -69,4 +78,46 @@ public function testCreatesSignedTag(): void
self::assertStringContainsString('a commit', $fetchedTag);
self::assertStringContainsString('-----BEGIN PGP SIGNATURE-----', $fetchedTag);
}

public function testSkipsIfTagAlreadyExists(): void
{
$tagName = 'name-of-the-tag';
$logger = $this->createMock(LoggerInterface::class);
$logger->expects(self::never())
->method('info');

$sourceUri = $this->createMock(UriInterface::class);
$sourceUri->method('__toString')->willReturn($this->repository);

$hasTag = new HasTagViaConsole();

(new CreateTagViaConsole($hasTag, $logger))(
$this->repository,
BranchName::fromName('tag-branch'),
$tagName,
'changelog text for the tag',
$this->key,
);

Shell\execute('git', ['tag', '-v', $tagName], $this->repository);
$fetchedTag = Shell\execute('git', ['show', $tagName], $this->repository);

self::assertStringContainsString('tag name-of-the-tag', $fetchedTag);
self::assertStringContainsString('changelog text for the tag', $fetchedTag);
self::assertStringContainsString('a commit', $fetchedTag);
self::assertStringContainsString('-----BEGIN PGP SIGNATURE-----', $fetchedTag);

$logger = $this->createMock(LoggerInterface::class);
$logger->expects(self::once())
->method('info')
->with(sprintf('[CreateTagViaConsole] Skipping this step; tag "%s" already exists.', $tagName));

(new CreateTagViaConsole($hasTag, $logger))(
$this->repository,
BranchName::fromName('tag-branch'),
$tagName,
'changelog text for the tag',
$this->key,
);
}
}
79 changes: 79 additions & 0 deletions test/unit/Git/HasTagViaConsoleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

declare(strict_types=1);

namespace Laminas\AutomaticReleases\Test\Unit\Git;

use Laminas\AutomaticReleases\Git\HasTag;
use Laminas\AutomaticReleases\Git\HasTagViaConsole;
use PHPUnit\Framework\TestCase;
use Psl\Env;
use Psl\Filesystem;
use Psl\Shell;

use function array_map;
use function sprintf;

/** @covers \Laminas\AutomaticReleases\Git\HasTagViaConsole */
final class HasTagViaConsoleTest extends TestCase
{
/** @var non-empty-string */
private string $repository;
private HasTag $hasTag;

protected function setUp(): void
{
parent::setUp();

$this->repository = Filesystem\create_temporary_file(Env\temp_dir(), 'HasTagViaConsoleRepository');

$this->hasTag = new HasTagViaConsole();

Filesystem\delete_file($this->repository);
Filesystem\create_directory($this->repository);

Shell\execute('git', ['init'], $this->repository);

Shell\execute('git', ['config', 'user.email', 'me@example.com'], $this->repository);
Shell\execute('git', ['config', 'user.name', 'Just Me'], $this->repository);

array_map(fn (string $tag) => $this->createTag($tag), [
'1.0.0',
'2.0.0',
]);
}

private function createTag(string $tag): void
{
Shell\execute('git', ['commit', '--allow-empty', '-m', 'a commit for version ' . $tag], $this->repository);
Shell\execute('git', ['tag', '-a', $tag, '-m', 'version ' . $tag], $this->repository);
}

/**
* @param non-empty-string $repository
* @param non-empty-string $tag
*/
private function assertGitTagExists(string $repository, string $tag): void
{
self::assertTrue(($this->hasTag)($repository, $tag), sprintf('Failed asserting git tag "%s" exists.', $tag));
}

/**
* @param non-empty-string $repository
* @param non-empty-string $tag
*/
private function assertGitTagMissing(string $repository, string $tag): void
{
self::assertFalse(($this->hasTag)($repository, $tag), sprintf('Failed asserting git tag "%s" is missing.', $tag));
}

public function testHasTag(): void
{
$this->assertGitTagExists($this->repository, '1.0.0');
}

public function testHasTagMissing(): void
{
$this->assertGitTagMissing($this->repository, '10.0.0');
}
}

0 comments on commit 12dde9b

Please sign in to comment.