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

#11 - create+switch default branch on release #12

Merged
merged 11 commits into from
Jul 28, 2020
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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).
Ocramius marked this conversation as resolved.
Show resolved Hide resolved

## 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
Ocramius marked this conversation as resolved.
Show resolved Hide resolved

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');
Ocramius marked this conversation as resolved.
Show resolved Hide resolved

$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;
Ocramius marked this conversation as resolved.
Show resolved Hide resolved
}

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

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

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

return 0;
}
}