Skip to content

Automatically generate changelog revision text if the changelog was not hand-crafted - do not commit if unchanged #58

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

Merged
merged 10 commits into from
Aug 26, 2020
Merged
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ All notable changes to this project will be documented in this file, in reverse

### Changed

- Nothing.
- [#58](https://github.com/laminas/automatic-releases/pull/58) updates the "Release" step such that:
- It now **always** uses jwage/changelog-generator to generate release notes.
- **IF** a `CHANGELOG.md` file is present:
- **IF** it contains changes for the target version, it appends the generated release notes to the changes for that version.
- **OTHERWISE** it replaces the contents for the target version with the generated release notes.
- And then it commits and pushes the file to the originating branch before it tags and releases.

### Deprecated

Expand Down
7 changes: 3 additions & 4 deletions bin/console.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
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\ConcatenateMultipleReleaseTexts;
use Laminas\AutomaticReleases\Github\CreateReleaseTextThroughChangelog;
use Laminas\AutomaticReleases\Github\CreateReleaseTextViaKeepAChangelog;
use Laminas\AutomaticReleases\Github\Event\Factory\LoadCurrentGithubEventFromGithubActionPath;
use Laminas\AutomaticReleases\Github\JwageGenerateChangelog;
use Laminas\AutomaticReleases\Github\MergeMultipleReleaseNotes;
use Laminas\AutomaticReleases\Gpg\ImportGpgKeyFromStringViaTemporaryFile;
use Lcobucci\Clock\SystemClock;
use Monolog\Handler\StreamHandler;
Expand Down Expand Up @@ -75,7 +75,6 @@ static function (int $errorCode, string $message = '', string $file = '', int $l
$commit = new CommitFileViaConsole();
$push = new PushViaConsole();
$commitChangelog = new CommitReleaseChangelogViaKeepAChangelog(
new SystemClock(),
$changelogExists,
$checkoutBranch,
$commit,
Expand All @@ -86,8 +85,8 @@ static function (int $errorCode, string $message = '', string $file = '', int $l
$makeRequests,
$httpClient
));
$createReleaseText = new ConcatenateMultipleReleaseTexts([
new CreateReleaseTextViaKeepAChangelog($changelogExists),
$createReleaseText = new MergeMultipleReleaseNotes([
new CreateReleaseTextViaKeepAChangelog($changelogExists, new SystemClock()),
$createCommitText,
]);
$createRelease = new CreateReleaseThroughApiCall(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example needs a better comment


name: "Automatic Releases"

on:
milestone:
types:
- "closed"

jobs:
release:
name: "GIT tag, release & create merge-up PR"
runs-on: ubuntu-latest

steps:
- name: "Checkout"
uses: "actions/checkout@v2"

- name: "Release"
uses: "laminas/automatic-releases@v1"
with:
command-name: "laminas:automatic-releases:release"
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 }}

- name: "Create Merge-Up Pull Request"
uses: "laminas/automatic-releases@v1"
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"
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 }}

- name: "Bump Changelog Version On Originating Release Branch"
uses: "laminas/automatic-releases@v1"
with:
command-name: "laminas:automatic-releases:bump-changelog"
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 }}
16 changes: 9 additions & 7 deletions src/Application/Command/CreateMergeUpPullRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,19 +94,21 @@ public function execute(InputInterface $input, OutputInterface $output): int
. uniqid('_', true) // This is to ensure that a new merge-up pull request is created even if one already exists
);

$releaseNotes = $this->createReleaseText->__invoke(
$this->getMilestone->__invoke($event->repository(), $event->milestoneNumber()),
$event->repository(),
$event->version(),
$releaseBranch,
$repositoryPath
);

$this->push->__invoke($repositoryPath, $releaseBranch->name(), $mergeUpBranch->name());
$this->createPullRequest->__invoke(
$event->repository(),
$mergeUpBranch,
$mergeUpTarget,
'Merge release ' . $releaseVersion->fullReleaseName() . ' into ' . $mergeUpTarget->name(),
$this->createReleaseText->__invoke(
$this->getMilestone->__invoke($event->repository(), $event->milestoneNumber()),
$event->repository(),
$event->version(),
$releaseBranch,
$repositoryPath
)
$releaseNotes->contents()
);

return 0;
Expand Down
16 changes: 11 additions & 5 deletions src/Application/Command/ReleaseCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,28 @@ public function execute(InputInterface $input, OutputInterface $output): int
sprintf('No valid release branch found for version %s', $releaseVersion->fullReleaseName())
);

($this->commitChangelog)($repositoryPath, $releaseVersion, $releaseBranch);

$changelog = ($this->createChangelogText)(
$changelogReleaseNotes = ($this->createChangelogText)(
$milestone,
$repositoryName,
$releaseVersion,
$releaseBranch,
$repositoryPath
);

($this->commitChangelog)($changelogReleaseNotes, $repositoryPath, $releaseVersion, $releaseBranch);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like how this now receives a pre-computed changelog 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought you might. 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This made me happy as well. The "commit, then create" from before worked, and was necessary based on what we were doing, but this makes sooooo much more sense.


$tagName = $releaseVersion->fullReleaseName();

($this->createTag)($repositoryPath, $releaseBranch, $tagName, $changelog, $this->environment->signingSecretKey());
($this->createTag)(
$repositoryPath,
$releaseBranch,
$tagName,
$changelogReleaseNotes->contents(),
$this->environment->signingSecretKey()
);
($this->push)($repositoryPath, $tagName);
($this->push)($repositoryPath, $tagName, $releaseVersion->targetReleaseBranchName()->name());
($this->createRelease)($repositoryName, $releaseVersion, $changelog);
($this->createRelease)($repositoryName, $releaseVersion, $changelogReleaseNotes->contents());

return 0;
}
Expand Down
101 changes: 101 additions & 0 deletions src/Changelog/ChangelogReleaseNotes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

declare(strict_types=1);

namespace Laminas\AutomaticReleases\Changelog;

use Phly\KeepAChangelog\Common\ChangelogEditor;
use Phly\KeepAChangelog\Common\ChangelogEntry;
use RuntimeException;
use Webmozart\Assert\Assert;

/**
* @psalm-immutable
*/
class ChangelogReleaseNotes
{
private const CONCATENATION_STRING = "\n\n-----\n\n";

private ?ChangelogEntry $changelogEntry;

/** @psalm-var non-empty-string */
private string $contents;

/**
* @psalm-param non-empty-string $changelogFile
*/
public static function writeChangelogFile(string $changelogFile, self $releaseNotes): void
{
// Nothing to do
if (! $releaseNotes->requiresUpdatingChangelogFile()) {
return;
}

Assert::notNull($releaseNotes->changelogEntry);

$editor = new ChangelogEditor();
$editor->update(
$changelogFile,
$releaseNotes->contents,
$releaseNotes->changelogEntry
);
}

/**
* @psalm-param non-empty-string $contents
*/
public function __construct(
string $contents,
?ChangelogEntry $changelogEntry = null
) {
if ($changelogEntry) {
$changelogEntry = clone $changelogEntry;
}

$this->contents = $contents;

/** @psalm-suppress ImpurePropertyAssignment */
$this->changelogEntry = $changelogEntry;
}

/**
* @psalm-return non-empty-string
*/
public function contents(): string
{
return $this->contents;
}

public function merge(self $next): self
{
if ($this->changelogEntry && $next->changelogEntry) {
throw new RuntimeException(
'Aborting: Both current release notes and next contain a ChangelogEntry;'
. ' only one CreateReleaseText implementation should resolve one.'
);
}

$changelogEntry = $this->changelogEntry ?: $next->changelogEntry;
if ($changelogEntry) {
$changelogEntry = clone $changelogEntry;
}

$merged = clone $this;
$merged->contents .= self::CONCATENATION_STRING . $next->contents;
/** @psalm-suppress ImpurePropertyAssignment */
$merged->changelogEntry = $changelogEntry;

return $merged;
}

public function requiresUpdatingChangelogFile(): bool
{
if ($this->changelogEntry === null) {
return false;
}

$originalContents = (string) $this->changelogEntry->contents();

return $this->contents !== $originalContents;
}
}
1 change: 1 addition & 0 deletions src/Changelog/CommitReleaseChangelog.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface CommitReleaseChangelog
* @psalm-param non-empty-string $repositoryDirectory
*/
public function __invoke(
ChangelogReleaseNotes $releaseNotes,
string $repositoryDirectory,
SemVerVersion $version,
BranchName $sourceBranch
Expand Down
Loading