Skip to content

Commit d28f993

Browse files
committed
#1594: Preliminary simple implementation
1 parent 7efd1c9 commit d28f993

5 files changed

Lines changed: 166 additions & 0 deletions

File tree

cli/src/main/java/com/devonfw/tools/ide/commandlet/CommandletManagerImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public CommandletManagerImpl(IdeContext context) {
119119
add(new UpgradeSettingsCommandlet(context));
120120
add(new CreateCommandlet(context));
121121
add(new BuildCommandlet(context));
122+
add(new ReleaseCommandlet(context));
122123
add(new InstallPluginCommandlet(context));
123124
add(new UninstallPluginCommandlet(context));
124125
add(new UpgradeCommandlet(context));
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package com.devonfw.tools.ide.commandlet;
2+
3+
import java.nio.file.Path;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
import java.util.Locale;
7+
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
10+
11+
import com.devonfw.tools.ide.cli.CliException;
12+
import com.devonfw.tools.ide.context.IdeContext;
13+
import com.devonfw.tools.ide.git.GitContext;
14+
import com.devonfw.tools.ide.property.StringProperty;
15+
import com.devonfw.tools.ide.tool.LocalToolCommandlet;
16+
import com.devonfw.tools.ide.tool.gradle.Gradle;
17+
import com.devonfw.tools.ide.tool.mvn.Mvn;
18+
import com.devonfw.tools.ide.tool.npm.Npm;
19+
import com.devonfw.tools.ide.tool.yarn.Yarn;
20+
21+
/**
22+
* {@link Commandlet} to perform a release of the current project. See <a href="https://github.com/devonfw/IDEasy/issues/1594">#1594</a>.
23+
*/
24+
public class ReleaseCommandlet extends Commandlet {
25+
26+
private static final Logger LOG = LoggerFactory.getLogger(ReleaseCommandlet.class);
27+
28+
private static final List<Class<? extends LocalToolCommandlet>> BUILD_TOOLS = List.of(Mvn.class, Gradle.class, Yarn.class, Npm.class);
29+
30+
public final StringProperty arguments;
31+
32+
public ReleaseCommandlet(IdeContext context) {
33+
34+
super(context);
35+
addKeyword(getName());
36+
this.arguments = add(new StringProperty("", false, true, "args"));
37+
}
38+
39+
@Override
40+
public String getName() {
41+
42+
return "release";
43+
}
44+
45+
@Override
46+
protected void doRun() {
47+
48+
Path projectPath = this.context.getCwd();
49+
GitContext git = this.context.getGitContext();
50+
51+
if (git.hasUntrackedFiles(projectPath)) {
52+
throw new CliException("Your project has uncommitted or untracked changes. Please commit or revert them before releasing.");
53+
}
54+
55+
String releaseVersion = this.context.askForInput("Enter the release version to publish (e.g. 1.5.0):");
56+
String nextVersion = getNextSnapshotVersion(releaseVersion);
57+
this.context.askToContinue("About to release version {} and then continue development on {}. Proceed?", releaseVersion, nextVersion);
58+
59+
setProjectVersion(projectPath, releaseVersion);
60+
git.commit(projectPath, "release/" + releaseVersion);
61+
git.tag(projectPath, "release/" + releaseVersion);
62+
63+
buildAndDeploy(projectPath);
64+
65+
setProjectVersion(projectPath, nextVersion);
66+
git.commit(projectPath, "set next development version " + nextVersion);
67+
git.push(projectPath);
68+
69+
LOG.info("Successfully released version {}.", releaseVersion);
70+
}
71+
72+
private String getNextSnapshotVersion(String releaseVersion) {
73+
74+
int lastDot = releaseVersion.lastIndexOf('.');
75+
String prefix = releaseVersion.substring(0, lastDot + 1);
76+
int lastNumber = Integer.parseInt(releaseVersion.substring(lastDot + 1));
77+
return prefix + (lastNumber + 1) + "-SNAPSHOT";
78+
}
79+
80+
private void setProjectVersion(Path projectPath, String version) {
81+
82+
Mvn mvn = getCommandlet(Mvn.class);
83+
mvn.runTool(List.of("versions:set", "-DnewVersion=" + version, "-DgenerateBackupPoms=false"));
84+
}
85+
86+
private void buildAndDeploy(Path projectPath) {
87+
88+
for (Class<? extends LocalToolCommandlet> toolClass : BUILD_TOOLS) {
89+
LocalToolCommandlet tool = getCommandlet(toolClass);
90+
if (tool.findBuildDescriptor(projectPath) != null) {
91+
String releaseOptsVariable = tool.getName().toUpperCase(Locale.ROOT) + "_RELEASE_OPTS";
92+
List<String> args = getReleaseOptions(releaseOptsVariable);
93+
args.addAll(this.arguments.asList());
94+
tool.runTool(args);
95+
return;
96+
}
97+
}
98+
throw new CliException("Could not find a build descriptor - no pom.xml, build.gradle, or package.json found!");
99+
}
100+
101+
private List<String> getReleaseOptions(String releaseOptsVariable) {
102+
103+
String value = this.context.getVariables().get(releaseOptsVariable);
104+
if ((value == null) || value.isBlank()) {
105+
return new ArrayList<>();
106+
}
107+
return new ArrayList<>(List.of(value.split(" ")));
108+
}
109+
}

cli/src/main/java/com/devonfw/tools/ide/git/GitContext.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,4 +245,27 @@ default void reset(Path repository, String branch) {
245245
* @param trackedCommitIdPath the path to the file where the commit Id will be written.
246246
*/
247247
void saveCurrentCommitId(Path repository, Path trackedCommitIdPath);
248+
249+
/**
250+
* Commits all currently changed files (tracked) in the given repository.
251+
*
252+
* @param repository the {@link Path} to the git repository.
253+
* @param message the commit message.
254+
*/
255+
void commit(Path repository, String message);
256+
257+
/**
258+
* Creates an annotated git tag in the given repository.
259+
*
260+
* @param repository the {@link Path} to the git repository.
261+
* @param tagName the name of the tag to create (e.g. "release/1.5.0").
262+
*/
263+
void tag(Path repository, String tagName);
264+
265+
/**
266+
* Pushes the local commits and tags of the given repository to the remote repository.
267+
*
268+
* @param repository the {@link Path} to the git repository.
269+
*/
270+
void push(Path repository);
248271
}

cli/src/main/java/com/devonfw/tools/ide/git/GitContextImpl.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,24 @@ public void saveCurrentCommitId(Path repository, Path trackedCommitIdPath) {
526526
protected String determineCurrentCommitId(Path repository) {
527527
return runGitCommandAndGetSingleOutput("Failed to get current commit id.", repository, "rev-parse", FILE_HEAD);
528528
}
529+
530+
@Override
531+
public void commit(Path repository, String message) {
532+
533+
runGitCommand(repository, "commit", "-a", "-m", message);
534+
}
535+
536+
@Override
537+
public void tag(Path repository, String tagName) {
538+
539+
runGitCommand(repository, "tag", "-a", tagName, "-m", tagName);
540+
}
541+
542+
@Override
543+
public void push(Path repository) {
544+
545+
runGitCommand(repository, "push", "--follow-tags");
546+
}
529547
}
530548

531549

cli/src/test/java/com/devonfw/tools/ide/git/GitContextMock.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,19 @@ public String determineRemote(Path repository) {
116116
public void saveCurrentCommitId(Path repository, Path trackedCommitIdPath) {
117117

118118
}
119+
120+
@Override
121+
public void commit(Path repository, String message) {
122+
123+
}
124+
125+
@Override
126+
public void tag(Path repository, String tagName) {
127+
128+
}
129+
130+
@Override
131+
public void push(Path repository) {
132+
133+
}
119134
}

0 commit comments

Comments
 (0)