Skip to content

Commit

Permalink
feature #23 Allow releases based on relative versions (sstok)
Browse files Browse the repository at this point in the history
This PR was merged into the 1.0-dev branch.

Discussion
----------

Allow `alpha | beta | rc | patch | minor | major | stable` as version for release command.

Closes #19

Commits
-------

0ad43b2 Add Version::increase() to get increased version
3aeaca3 Allow releases based on relative versions
  • Loading branch information
sstok committed Feb 11, 2017
2 parents 0b0e028 + 3aeaca3 commit cee3cdb
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 2 deletions.
6 changes: 5 additions & 1 deletion src/Cli/Handler/ReleaseHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,11 @@ private function validateBranchCompatibility(string $branch, Version $version)

private function validateVersion(string $version): Version
{
$version = Version::fromString($version);
if (in_array(strtolower($version), ['alpha', 'beta', 'rc', 'stable', 'major', 'minor', 'patch'], true)) {
$version = Version::fromString($this->git->getLastTagOnBranch())->increase(strtolower($version));
} else {
$version = Version::fromString($version);
}

if (!$this->io->isInteractive()) {
return $version;
Expand Down
2 changes: 1 addition & 1 deletion src/Cli/HubKitApplicationConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ function (PreHandleEvent $event) {

->beginCommand('release')
->setDescription('Make a new release for the current branch')
->addArgument('version', Argument::REQUIRED | Argument::STRING, 'Version to make')
->addArgument('version', Argument::REQUIRED | Argument::STRING, 'Version to make (supports relative, eg. minor, alpha, ...)')
->addOption('all-categories', null, Option::NO_VALUE | Option::BOOLEAN, 'Show all categories (including empty)')
->addOption('no-edit', null, Option::NO_VALUE | Option::BOOLEAN, 'Don\'t open the editor for editing the release page')
->addOption('pre-release', null, Option::NO_VALUE | Option::BOOLEAN, 'Mark as pre-release (not production ready)')
Expand Down
71 changes: 71 additions & 0 deletions src/Helper/Version.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,75 @@ public function equalTo(Version $second): bool
{
return $this->full === $second->full;
}

/**
* Returns the increased Version based on the stability.
*
* Note. Using 'major' on a beta release will create a stable release
* for that major version. Using 'stable' on an existing stable will increase
* minor.
*
* @param string $stability Eg. alpha, beta, rc, stable, major, minor, patch
*
* @return Version A new version instance with the changes applied
*/
public function increase(string $stability): Version
{
switch ($stability) {
case 'patch':
if ($this->major > 0 && $this->metaver > 0) {
throw new \InvalidArgumentException('Cannot increase patch for an unstable version.');
}

return new self($this->major, $this->minor, $this->patch + 1, 3);

case 'minor':
return new self($this->major, $this->minor + 1, 0, 3);

case 'major':
if ($this->stability < 3) {
return new self($this->major > 0 ? $this->major : $this->major + 1, 0, 0, 3);
}

return new self($this->major + 1, 0, 0, 3);

case 'alpha':
case 'beta':
case 'rc':
return $this->increaseMetaver($stability);

case 'stable':
return $this->increaseStable();

default:
throw new \InvalidArgumentException(
sprintf(
'Unknown stability "%s", accepts "%s" '.$stability,
implode('", "', ['alpha', 'beta', 'rc', 'stable', 'major', 'minor', 'patch'])
)
);
}
}

private function increaseMetaver(string $stability): Version
{
if ($this->stability === self::$stabilises[$stability]) {
return new self($this->major, $this->minor, 0, $this->stability, $this->metaver + 1);
}

if (self::$stabilises[$stability] > $this->stability) {
return new self($this->major, $this->minor, 0, self::$stabilises[$stability], 1);
}

return new self($this->major, $this->minor + 1, 0, self::$stabilises[$stability], 1);
}

private function increaseStable(): Version
{
if ($this->stability < 3) {
return new self(max($this->major, 1), 0, 0, 3);
}

return new self($this->major, $this->minor + 1, 0, 3);
}
}
26 changes: 26 additions & 0 deletions tests/Handler/ReleaseHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,32 @@ public function it_asks_confirmation_when_target_branch_has_a_mismatch_and_abort
$this->executeHandler($args); // default answer is no
}

/** @test */
public function it_creates_a_new_release_with_a_relative_version()
{
$this->expectTags(['0.1.0', '1.0.0', '2.0.0']);
$this->git->getLastTagOnBranch()->willReturn('2.5.0');
$this->expectMatchingVersionBranchNotExists('3.0');

$this->git->getLogBetweenCommits('2.5.0', 'master')->willReturn(self::COMMITS);

$this->expectEditorReturns("### Added\n- Introduce a new API for ValuesBag", 'Drop support for older PHP versions');

$url = $this->expectTagAndGitHubRelease('3.0.0', 'Drop support for older PHP versions');

$args = $this->getArgs('major');
$this->executeHandler($args);

$this->assertOutputMatches(
[
'Preparing release 3.0.0 (target branch master)',
'Please wait...',
'Successfully released 3.0.0',
$url,
]
);
}

private function getArgs(string $version): Args
{
$format = ArgsFormat::build()
Expand Down
59 changes: 59 additions & 0 deletions tests/Helper/VersionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,63 @@ public function it_provides_next_version_candidates($current, $expected)

self::assertEquals($expected, $candidates);
}

public function provideExpectedIncreasedVersion(): array
{
return [
'patch with patch 0' => ['0.1.0', '0.1.1', 'patch'],
'patch with patch 1' => ['0.1.1', '0.1.2', 'patch'],

// Minor, patch must be reset
'minor with patch 0' => ['0.1.0', '0.2.0', 'minor'],
'minor with patch 1' => ['0.1.1', '0.2.0', 'minor'],

// Major, minor and patch must be reset
'major.0.0' => ['0.1.0', '1.0.0', 'major'],
'major.1.0' => ['0.1.0', '1.0.0', 'major'],
'major.1.1' => ['0.1.1', '1.0.0', 'major'],
'major from beta' => ['1.0.0-beta1', '1.0.0', 'major'],
'major from 1.0' => ['1.0.0', '2.0.0', 'major'],
'major from 2.0-beta' => ['2.0.0-beta1', '2.0.0', 'major'],

// Alpha
'next alpha' => ['1.0.0-alpha1', '1.0.0-alpha2', 'alpha'],
'new alpha' => ['1.0.0', '1.1.0-alpha1', 'alpha'],

// Beta
'next beta' => ['1.0.0-beta1', '1.0.0-beta2', 'beta'],
'new beta' => ['1.0.0', '1.1.0-beta1', 'beta'],
'new beta from alpha' => ['1.0.0-alpha1', '1.0.0-beta1', 'beta'],

// RC
'next rc' => ['1.0.0-rc1', '1.0.0-rc2', 'rc'],
'new rc' => ['1.0.0', '1.1.0-rc1', 'rc'],
'new rc from alpha' => ['1.0.0-alpha1', '1.0.0-rc1', 'rc'],
'new rc from beta' => ['1.0.0-beta1', '1.0.0-rc1', 'rc'],

// Stable
'new stable from 0.0' => ['0.1.0', '1.0.0', 'stable'],
'new stable from alpha' => ['1.0.0-alpha6', '1.0.0', 'stable'],
'new stable from beta' => ['1.0.0-beta1', '1.0.0', 'stable'],
'new stable from current stable' => ['1.0.0', '1.1.0', 'stable'],
];
}

/**
* @test
* @dataProvider provideExpectedIncreasedVersion
*/
public function it_increases_to_next_version(string $current, string $expected, $stability)
{
self::assertEquals(Version::fromString($expected), Version::fromString($current)->increase($stability));
}

/** @test */
public function it_cannot_increases_patch_on_unstable()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Cannot increase patch for an unstable version.');

Version::fromString('1.0.0-beta1')->increase('patch');
}
}

0 comments on commit cee3cdb

Please sign in to comment.