Skip to content

add an option to create annotated tags #22

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 13 commits into from
May 11, 2021
Merged
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- `tagMessage` allows to create annotated tags when publishing new versions. ([#22](https://github.com/diffplug/spotless-changelog/pull/22))

## [2.1.2] - 2021-04-10
### Fixed
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ spotlessChangelog { // all defaults
// tag and push
tagPrefix 'release/'
commitMessage 'Published release/{{version}}' // {{version}} will be replaced
tagMessage null // default is null (creates lightweight tag); {{changes}} and {{version}} will be replaced
remote 'origin'
branch 'main'
// default value is `yes`, but if you set it to `no`, then it will
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2020 DiffPlug
* Copyright (C) 2019-2021 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -35,7 +35,6 @@ public class Changelog {
private static final String VERSION_BEGIN = "\n## [";
private static final String UNRELEASED = VERSION_BEGIN + "Unreleased]";
private static final String DONT_PARSE_BELOW_HERE = "\n<!-- END CHANGELOG -->";

private final boolean windowsNewlines;
private final PoolString dontParse, beforeUnreleased;
private final List<VersionEntry> versionsRaw;
Expand Down Expand Up @@ -166,6 +165,15 @@ public static class VersionEntry {

private VersionEntry() {}

private VersionEntry copy() {
VersionEntry copy = new VersionEntry();
copy.version = version;
copy.date = date;
copy.headerMisc = headerMisc;
copy.changes = changes;
return copy;
}

/** Creates a VersionHeader of the given version and date. */
public static VersionEntry versionDate(String version, String date) {
VersionEntry header = new VersionEntry();
Expand Down Expand Up @@ -313,7 +321,8 @@ public Changelog releaseUnreleased(String version, String date) {

VersionEntry entry = VersionEntry.versionDate(version, date);
entry.setChanges(unreleased.changes());
unreleased.setChanges("\n");

list.set(0, unreleased.copy().setChanges("\n"));
list.add(1, entry);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.function.Consumer;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.api.TagCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
Expand Down Expand Up @@ -57,7 +58,6 @@ public class GitActions implements AutoCloseable {
repository = new FileRepositoryBuilder()
.findGitDir(changelogFile)
.build();
repository.getWorkTree();
git = new Git(repository);
}

Expand Down Expand Up @@ -87,23 +87,35 @@ public void assertNoTag() throws IOException {

/** Adds and commits the changelog. */
public void addAndCommit() throws GitAPIException {
String commitMsg = cfg.commitMessage.replace(GitCfg.COMMIT_MESSAGE_VERSION, model.versions().next());
String path = repository.getWorkTree().toPath().relativize(changelogFile.toPath()).toString();
git.add()
.addFilepattern(path)
.call();
git.commit()
.setMessage(commitMsg)
.setMessage(formatCommitMessage(cfg.commitMessage))
.call();
}

/** Tags and pushes the tag and the branch. */
/** Tags and pushes the tag and the branch. */
public void tagBranchPush() throws GitAPIException {
Ref tagRef = git.tag().setName(tagName()).setAnnotated(false).call();
push(tagRef, RemoteRefUpdate.Status.OK);
TagCommand tagCommand = git.tag().setName(tagName());
if (cfg.tagMessage != null) {
tagCommand.setAnnotated(true).setMessage(formatTagMessage(cfg.tagMessage));
}
push(tagCommand.call(), RemoteRefUpdate.Status.OK);
push(cfg.branch, RemoteRefUpdate.Status.OK);
}

private String formatCommitMessage(final String commitMessage) {
return commitMessage.replace(GitCfg.COMMIT_MESSAGE_VERSION, model.versions().next());
}

private String formatTagMessage(final String tagMessage) {
return formatCommitMessage(tagMessage)
.replace(GitCfg.TAG_MESSAGE_CHANGES, model.changelog().unreleasedChanges())
.replace(GitCfg.COMMIT_MESSAGE_VERSION, model.versions().next());
}

private String tagName() {
return cfg.tagPrefix + model.versions().next();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@
/** Configuration for committing, tagging, and pushing the next version. */
public class GitCfg {
public static final String COMMIT_MESSAGE_VERSION = "{{version}}";
public static final String TAG_MESSAGE_CHANGES = "{{changes}}";

/** Prefix used for release tags, default is `release/`. */
public String tagPrefix = "release/";
/** Message used for release commits, default is `Published release/{{version}}`. */
public String commitMessage = "Published release/" + COMMIT_MESSAGE_VERSION;
/** Message used in tag, null means lightweight tag. */
public String tagMessage = null;
public String remote = "origin";
public String branch = "main";
public String sshStrictHostKeyChecking = "yes";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ public void commitMessage(String commitMessage) {
gitCfg.commitMessage = GitCfg.validateCommitMessage(commitMessage);
}

/** Default value is null (creates a lightweight tag) - {{changes}} and {{version}} will be replaced. */
public void tagMessage(String tagMessage) {
gitCfg.tagMessage = tagMessage;
}

/** Default value is 'origin' */
public void remote(String remote) {
gitCfg.remote = remote;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright (C) 2019-2021 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.spotless.changelog.gradle;

import static org.junit.Assert.assertEquals;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;

public class ChangelogPluginPushTest extends GradleHarness {

@Rule
public DeleteOnSuccessTemporaryFolder temporaryFolder = new DeleteOnSuccessTemporaryFolder(new File("build"));
@Rule
public KeepTempFolderOnFailure keepTempFolderOnFailure = new KeepTempFolderOnFailure(temporaryFolder);

@Test
public void verifyAnnotatedTagMessage() throws IOException, GitAPIException {

final String testCaseFolder = "1.0.3-annotatedTag";
File origin = initUpstreamRepo(testCaseFolder);

final File working = temporaryFolder.newFolder("working");
Git git = Git.cloneRepository().setURI(origin.getAbsolutePath())
.setDirectory(working).call();

copyResourceFile(working, testCaseFolder, "CHANGELOG.md");

gradleRunner().withProjectDir(working)/*.withDebug(true)*/
.withArguments("changelogPush").build();

assertEquals("Version is 1.0.3, here are the changes:"
+ "\n\n### Fixed\n"
+ "- this should be in tag message\n",
annotatedTagMessage(git, "release/1.0.3"));
}

private String annotatedTagMessage(Git localGit, final String tagName) throws IOException {
try (RevWalk walk = new RevWalk(localGit.getRepository())) {
return walk.parseTag(
localGit.getRepository().findRef(tagName).getObjectId())
.getFullMessage();
}
}

private File initUpstreamRepo(String testCaseFolder) throws IOException, GitAPIException {
File origin = temporaryFolder.newFolder("origin");
Git git = Git.init().setDirectory(origin).call();
copyResourceFile(origin, "settings.gradle");
copyResourceFile(origin, testCaseFolder, "build.gradle");
git.add().addFilepattern(".").call();
git.commit()
.setMessage("Commit all changes including additions")
.call();
return origin;
}

private void copyResourceFile(File working, String testCaseFolder, String fileName) throws IOException {
Files.copy(Paths.get("src/test/resources", testCaseFolder, fileName), working.toPath().resolve(fileName));
}

private void copyResourceFile(File working, String fileName) throws IOException {
Files.copy(Paths.get("src/test/resources", fileName), working.toPath().resolve(fileName));
}

static class KeepTempFolderOnFailure extends TestWatcher {
private final DeleteOnSuccessTemporaryFolder folder;

KeepTempFolderOnFailure(DeleteOnSuccessTemporaryFolder folder) {
this.folder = folder;
}

@Override
protected void failed(Throwable e, Description description) {
folder.disableDeletion();
}
}

static class DeleteOnSuccessTemporaryFolder extends TemporaryFolder {

boolean canDelete = true;

public DeleteOnSuccessTemporaryFolder(File file) {
super(file);
}

@Override
protected void after() {
if (canDelete)
super.after();
}

public void disableDeletion() {
canDelete = false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Changelog

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Fixed
- this should be in tag message

## [1.0.2] - 2021-04-23

Initial release.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
plugins {
id 'com.diffplug.spotless-changelog'
}

spotlessChangelog {
branch 'master'
tagMessage 'Version is {{version}}, here are the changes:{{changes}}'
}
Empty file.