Skip to content

Commit

Permalink
Merge pull request #12 from laminas/feature/#11-add-default-branch-sw…
Browse files Browse the repository at this point in the history
…itching

#11 - create+switch default branch on release
  • Loading branch information
Ocramius committed Jul 28, 2020
2 parents 0fc020d + 20ac681 commit 1d4b0b9
Show file tree
Hide file tree
Showing 19 changed files with 973 additions and 110 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/automatic-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,13 @@ jobs:
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}

- name: "Create and/or Switch to new Release Branch"
uses: "./"
with:
command-name: "laminas:automatic-releases:switch-default-branch-to-next-minor"
env:
"GITHUB_TOKEN": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ to your project or organisation:
* `GIT_AUTHOR_EMAIL` - email address of the author of your releases: can be an email address of a bot account.
* `SIGNING_SECRET_KEY` - a **password-less** private GPG key in ASCII format, to be used for signing your releases:
please use a dedicated GPG subkey for this purpose. Unsigned releases are not supported, and won't be supported.
* `ORGANIZATION_ADMIN_TOKEN` - if you use the file from [`examples/.github/workflows/release-on-milestone-closed.yml`](examples/.github/workflows/release-on-milestone-closed.yml),
then you have to provide a `ORGANIZATION_ADMIN_TOKEN`, which is a github token with administrative rights over
your organisation (issued by a user that has administrative rights over your project).
This is required for the `laminas:automatic-releases:switch-default-branch-to-next-minor`
command, because [changing default branch of a repository currently requires administrative token rights](https://developer.github.com/v3/repos/#update-a-repository).
You can generate a token from your [personal access tokens page](https://github.com/settings/tokens/new).

## Usage

Expand All @@ -41,6 +47,8 @@ this action will perform all following steps (or stop with an error):
5. create a tag named `x.y.z` on the selected branch, with the generated changelog
6. publish a release named `x.y.z`, with the generated tag and changelog
7. create (if applicable), a pull request from the selected branch to the next release branch
8. create (if necessary) a "next minor" release branch `x.y+1.z`
9. switch default repository branch to newest release branch

Please read the [`feature/`](./feature) specification for more detailed scenarios on how the tool is supposed
to operate.
6 changes: 5 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ description: 'Automates automatic releases for semver-compliant repositories'

inputs:
command-name:
description: 'Command to execute: one of "laminas:automatic-releases:release" or "laminas:automatic-releases:create-merge-up-pull-request"'
description: |
Command to execute: one of
* `laminas:automatic-releases:release`
* `laminas:automatic-releases:create-merge-up-pull-request`
* `laminas:automatic-releases:switch-default-branch-to-next-minor`
required: true

runs:
Expand Down
14 changes: 14 additions & 0 deletions bin/console.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Http\Discovery\Psr17FactoryDiscovery;
use Laminas\AutomaticReleases\Application\Command\CreateMergeUpPullRequest;
use Laminas\AutomaticReleases\Application\Command\ReleaseCommand;
use Laminas\AutomaticReleases\Application\Command\SwitchDefaultBranchToNextMinor;
use Laminas\AutomaticReleases\Environment\EnvironmentVariables;
use Laminas\AutomaticReleases\Git\CreateTagViaConsole;
use Laminas\AutomaticReleases\Git\FetchAndSetCurrentUserByReplacingCurrentOriginRemote;
Expand All @@ -19,6 +20,7 @@
use Laminas\AutomaticReleases\Github\Api\GraphQL\RunGraphQLQuery;
use Laminas\AutomaticReleases\Github\Api\V3\CreatePullRequestThroughApiCall;
use Laminas\AutomaticReleases\Github\Api\V3\CreateReleaseThroughApiCall;
use Laminas\AutomaticReleases\Github\Api\V3\SetDefaultBranchThroughApiCall;
use Laminas\AutomaticReleases\Github\CreateReleaseTextThroughChangelog;
use Laminas\AutomaticReleases\Github\Event\Factory\LoadCurrentGithubEventFromGithubActionPath;
use Laminas\AutomaticReleases\Github\JwageGenerateChangelog;
Expand Down Expand Up @@ -93,6 +95,18 @@ static function (int $errorCode, string $message = '', string $file = '', int $l
$githubToken
)
),
new SwitchDefaultBranchToNextMinor(
$variables,
$loadEvent,
$fetch,
$getCandidateBranches,
$push,
new SetDefaultBranchThroughApiCall(
$makeRequests,
$httpClient,
$githubToken
)
),
]);

$application->run();
Expand Down
14 changes: 12 additions & 2 deletions examples/.github/workflows/release-on-milestone-closed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
uses: "actions/checkout@v2"

- name: "Release"
uses: "laminas/automatic-releases@v1"
uses: "laminas/automatic-releases@v1.0.0"
with:
command-name: "laminas:automatic-releases:release"
env:
Expand All @@ -27,11 +27,21 @@ jobs:
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}

- name: "Create Merge-Up Pull Request"
uses: "laminas/automatic-releases@v1"
uses: "laminas/automatic-releases@v1.0.0"
with:
command-name: "laminas:automatic-releases:create-merge-up-pull-request"
env:
"GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}

- name: "Create and/or Switch to new Release Branch"
uses: "laminas/automatic-releases@v1.0.0"
with:
command-name: "laminas:automatic-releases:switch-default-branch-to-next-minor"
env:
"GITHUB_TOKEN": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
56 changes: 39 additions & 17 deletions feature/automated-releases.feature
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ Feature: Automated releases

Scenario: If no major release branch exists, the tool should not create a new major release
Given following existing branches:
| name |
| 1.0.x |
| name |
| 1.0.x |
| master |
| develop |
And following open milestones:
| name |
| 2.0.0 |
Expand All @@ -13,8 +15,10 @@ Feature: Automated releases

Scenario: If no major release branch exists, the tool should not create a new minor release
Given following existing branches:
| name |
| 1.0.x |
| name |
| 1.0.x |
| master |
| develop |
And following open milestones:
| name |
| 1.1.0 |
Expand All @@ -23,39 +27,57 @@ Feature: Automated releases

Scenario: If a major release branch exists, the tool creates a major release from there
Given following existing branches:
| name |
| 1.0.x |
| master |
| name |
| 1.0.x |
| 2.0.x |
| master |
| develop |
And following open milestones:
| name |
| 2.0.0 |
When I close milestone "2.0.0"
Then tag "2.0.0" should have been created on branch "master"
And branch "2.0.x" should have been created from "master"
Then tag "2.0.0" should have been created on branch "2.0.x"

Scenario: If a major release branch exists, the tool creates a new minor release from there
Scenario: If a new major release branch exists, the tool does not create a new minor release
Given following existing branches:
| name |
| 1.0.x |
| master |
| name |
| 1.0.x |
| 2.0.x |
| master |
| develop |
And following open milestones:
| name |
| 1.1.0 |
When I close milestone "1.1.0"
Then tag "1.1.0" should have been created on branch "master"
And branch "1.1.x" should have been created from "master"
Then the tool should have halted with an error

Scenario: If a minor release branch exists, the tool creates a new minor release from there
Scenario: If a minor release branch exists, when closing the minor release milestone,
the tool tags the minor release from the branch, and creates a pull request
against the next newer minor release branch.
Given following existing branches:
| name |
| 1.1.x |
| 1.2.x |
| master |
And following open milestones:
| name |
| 1.1.0 |
When I close milestone "1.1.0"
Then tag "1.1.0" should have been created on branch "1.1.x"
And a new pull request from branch "1.1.x" to "master" should have been created
And a new pull request from branch "1.1.x" to "1.2.x" should have been created

Scenario: If no newer release branch exists, the tool will not create any pull requests
Given following existing branches:
| name |
| 1.1.x |
| master |
| develop |
And following open milestones:
| name |
| 1.1.0 |
When I close milestone "1.1.0"
Then tag "1.1.0" should have been created on branch "1.1.x"
And no new pull request should have been created

Scenario: If a minor release branch exists, the tool creates a new patch release from there
Given following existing branches:
Expand Down
84 changes: 84 additions & 0 deletions feature/default-branch-switching.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
@manually-tested
Feature: Default branch switching

Scenario: A new minor branch is created and set as default branch on release
Given following existing branches:
| branch |
| 1.0.x |
| 1.1.x |
| 1.2.x |
And following open milestones:
| name |
| 1.2.0 |
And the default branch is "1.0.x"
When I close milestone "1.2.0"
Then these should be the existing branches:
| branch |
| 1.0.x |
| 1.1.x |
| 1.2.x |
| 1.3.x |
And the default branch should be "1.3.x"

Scenario: The latest pre-existing minor release branch is set as default branch on a successful release
Given following existing branches:
| branch |
| 1.0.x |
| 1.1.x |
| 1.2.x |
| 1.3.x |
And following open milestones:
| name |
| 1.2.0 |
And the default branch is "1.0.x"
When I close milestone "1.2.0"
Then these should be the existing branches:
| branch |
| 1.0.x |
| 1.1.x |
| 1.2.x |
| 1.3.x |
And the default branch should be "1.3.x"

Scenario: A pre-existing branch of a greater major release is set as default branch on release
Given following existing branches:
| branch |
| 1.0.x |
| 1.1.x |
| 1.2.x |
| 2.0.x |
| 2.1.x |
And following open milestones:
| name |
| 1.2.0 |
And the default branch is "1.0.x"
When I close milestone "1.2.0"
Then these should be the existing branches:
| branch |
| 1.0.x |
| 1.1.x |
| 1.2.x |
| 2.0.x |
| 2.1.x |
And the default branch should be "2.1.x"

Scenario: Branch is not switched when no minor release branch exists
Given following existing branches:
| branch |
| foo |
| bar |
| master |
| develop |
And following open milestones:
| name |
| 1.2.0 |
And the default branch is "develop"
When I close milestone "1.2.0"
Then these should be the existing branches:
| branch |
| foo |
| bar |
| master |
| develop |
And the default branch should be "develop"

4 changes: 2 additions & 2 deletions infection.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
"mutators": {
"@default": true
},
"minMsi": 59,
"minCoveredMsi": 59
"minMsi": 62,
"minCoveredMsi": 62
}
82 changes: 82 additions & 0 deletions src/Application/Command/SwitchDefaultBranchToNextMinor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

declare(strict_types=1);

namespace Laminas\AutomaticReleases\Application\Command;

use Laminas\AutomaticReleases\Environment\Variables;
use Laminas\AutomaticReleases\Git\Fetch;
use Laminas\AutomaticReleases\Git\GetMergeTargetCandidateBranches;
use Laminas\AutomaticReleases\Git\Push;
use Laminas\AutomaticReleases\Github\Api\V3\SetDefaultBranch;
use Laminas\AutomaticReleases\Github\Event\Factory\LoadCurrentGithubEvent;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Webmozart\Assert\Assert;

final class SwitchDefaultBranchToNextMinor extends Command
{
private Variables $variables;
private LoadCurrentGithubEvent $loadGithubEvent;
private Fetch $fetch;
private GetMergeTargetCandidateBranches $getMergeCandidates;
private Push $push;
private SetDefaultBranch $switchDefaultBranch;

public function __construct(
Variables $variables,
LoadCurrentGithubEvent $loadGithubEvent,
Fetch $fetch,
GetMergeTargetCandidateBranches $getMergeCandidates,
Push $push,
SetDefaultBranch $switchDefaultBranch
) {
parent::__construct('laminas:automatic-releases:switch-default-branch-to-next-minor');

$this->variables = $variables;
$this->loadGithubEvent = $loadGithubEvent;
$this->fetch = $fetch;
$this->getMergeCandidates = $getMergeCandidates;
$this->push = $push;
$this->switchDefaultBranch = $switchDefaultBranch;
}

public function execute(InputInterface $input, OutputInterface $output): int
{
$event = $this->loadGithubEvent->__invoke();
$repositoryPath = $this->variables->githubWorkspacePath();

Assert::directory($repositoryPath . '/.git');

$this->fetch->__invoke(
$event->repository()
->uriWithTokenAuthentication($this->variables->githubToken()),
$repositoryPath
);

$mergeCandidates = $this->getMergeCandidates->__invoke($repositoryPath);
$releaseVersion = $event->version();
$newestBranch = $mergeCandidates->newestReleaseBranch();

if ($newestBranch === null) {
$output->writeln('No stable branches found: cannot switch default branch');

return 0;
}

$nextDefaultBranch = $mergeCandidates->newestFutureReleaseBranchAfter($releaseVersion);

if (! $mergeCandidates->contains($nextDefaultBranch)) {
$this->push->__invoke(
$repositoryPath,
$newestBranch->name(),
$nextDefaultBranch->name()
);
}

$this->switchDefaultBranch->__invoke($event->repository(), $nextDefaultBranch);

return 0;
}
}

0 comments on commit 1d4b0b9

Please sign in to comment.