Skip to content

#1594: Implement release commandlet#2023

Open
laert-ll wants to merge 12 commits into
devonfw:mainfrom
laert-ll:feature/1594-implement-release-commandlet
Open

#1594: Implement release commandlet#2023
laert-ll wants to merge 12 commits into
devonfw:mainfrom
laert-ll:feature/1594-implement-release-commandlet

Conversation

@laert-ll

@laert-ll laert-ll commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

This PR fixes #1594

Implemented changes:

  • Added ide release commandlet that automates building and deploying a release: derives the release version from .mvn/maven.config (-Drevision=), commits and tags it, runs the Maven deploy build, bumps to the next -SNAPSHOT version, and pushes after confirmation.
  • Guards: aborts on uncommitted changes, warns when run on a fork, and requires the top-level project (or --force).
  • Build goals are configurable via MVN_RELEASE_OPTS (default clean deploy -Dchangelist= -Pdeploy); failed builds can be retried.
  • Added commit, tag, push, and retrieveGitRemotes to GitContext.

Testing instructions

  1. In a project using -Drevision= versioning (e.g. IDEasy itself), run ide release from the project root.
  2. Confirm it proposes the correct release/next versions, then creates the set release version commit + release/ tag, builds, and creates the set next version commit.
  3. Answer no at the final "Do you want to continue?" prompt to abort before pushing — verify nothing is pushed. To clean up: git reset --hard HEAD~2 && git tag -d release/.

Checklist for this PR

Make sure everything is checked before merging this PR. For further info please also see
our DoD.

  • When running mvn clean test locally all tests pass and build is successful
  • PR title is of the form #«issue-id»: «brief summary» (e.g. #921: fixed setup.bat). If no issue ID exists, title only.
  • PR top-level comment summarizes what has been done and contains link to addressed issue(s)
  • PR and issue(s) have suitable labels
  • Issue is set to In Progress and assigned to you or there is no issue (might happen for very small PRs)
  • You followed all coding conventions
  • You have added the issue implemented by your PR in CHANGELOG.adoc unless issue is labeled
    with internal
  • You have formulated clear instructions on how to test your contribution under "Testing instructions"

@github-project-automation github-project-automation Bot moved this to 🆕 New in IDEasy board Jun 15, 2026
@laert-ll laert-ll self-assigned this Jun 15, 2026
@laert-ll laert-ll force-pushed the feature/1594-implement-release-commandlet branch from 13ab4c6 to d28f993 Compare June 15, 2026 13:26
@laert-ll laert-ll moved this from 🆕 New to 🏗 In progress in IDEasy board Jun 16, 2026
@laert-ll laert-ll force-pushed the feature/1594-implement-release-commandlet branch from d491923 to 0547ac4 Compare June 16, 2026 10:42
@laert-ll laert-ll force-pushed the feature/1594-implement-release-commandlet branch from 78e6ead to d9c6911 Compare June 25, 2026 07:19
@coveralls

coveralls commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 29108746467

Coverage decreased (-0.03%) to 72.199%

Details

  • Coverage decreased (-0.03%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • 55 coverage regressions across 3 files.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

55 previously-covered lines in 3 files lost coverage.

File Lines Losing Coverage Coverage
com/devonfw/tools/ide/git/GitContextImpl.java 46 37.53%
com/devonfw/tools/ide/commandlet/CommandletManagerImpl.java 7 91.83%
com/devonfw/tools/ide/version/VersionSegment.java 2 90.81%

Coverage Stats

Coverage Status
Relevant Lines: 16798
Covered Lines: 12642
Line Coverage: 75.26%
Relevant Branches: 7496
Covered Branches: 4898
Branch Coverage: 65.34%
Branches in Coverage %: Yes
Coverage Strength: 3.19 hits per line

💛 - Coveralls

@laert-ll laert-ll marked this pull request as ready for review June 26, 2026 08:35
@laert-ll laert-ll moved this from 🏗 In progress to Team Review in IDEasy board Jun 26, 2026
@laert-ll laert-ll added release related to release commandlet and releases of IDEasy commandlet ide sub-command git git version management tool integration devonfw-ide backward compatibility for devonfw-ide (regression) labels Jul 9, 2026
@hohwille hohwille added this to the release:2026.07.002 milestone Jul 10, 2026
@hohwille hohwille moved this from Team Review to 👀 In review in IDEasy board Jul 10, 2026

@hohwille hohwille left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@laert-ll thank you for your PR. Great work 👍
Since this was somehow stuck in team-review without a reviewer assigned and I came across, I took the fast lane and moved it to the final review.
Regarding my reivew comments you did nothing wrong. I just want to improve the design for better SoC, reuse and maintainability.

Comment on lines +27 to +29
private static final String REVISION_FLAG = "-Drevision=";

private static final String DEFAULT_MVN_RELEASE_OPTS = "clean deploy -Dchangelist= -Pdeploy";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you please follow SoC and delegate the build to the according commandlet (here Mvn).
I would create an interface BuildTool that has a methods like

  • buildAndDeploy()
  • getProjectVersion(Path projectPath)
  • setProjectVersion(Path projectPath, VersionIdentifier version)
    and implement this interface in Mvn (we can later also implement it in Gralde, Npm, Yarn so we support doing releases with them without the need ti change the ReleaseCommandlet).

Therefore have a look how our BuildCommandlet is implemented:
It can already automatically check if there is a pom.xml file and then will invoke mvn and if it finds a build.gradle it will call gradle and in case of package.json it will use npm or yarn depending on the presence of a yarn.lock or not.
However, the BuildCommandlet itself has absolutely no knowledge about pom.xml, package.json, etc. nor of the default build option variables.
We should reuse the same infrastructure and design this commandlet in a similar way.

Comment on lines +131 to +139
private String getNextVersion(String version) {

int lastDot = version.lastIndexOf('.');
String prefix = version.substring(0, lastDot + 1);
String lastSegment = version.substring(lastDot + 1);
String incrementedSegment = String.valueOf(Long.parseLong(lastSegment) + 1);
incrementedSegment = "0".repeat(lastSegment.length() - incrementedSegment.length()) + incrementedSegment;
return prefix + incrementedSegment;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Instead of bash-hacking we now have Java and can avoid such "string-fiddling".
Please reuse what we already have implemented:

/**
* Increment the specified segment. For examples see {@code VersionIdentifierTest.testIncrement()}.
*
* @param digitNumber the index of the {@link VersionSegment} to increment. All segments before will remain untouched and all following segments will be
* set to zero.
* @param keepLetters {@code true} to keep {@link VersionSegment#getLetters() letters} from modified segments, {@code false} to drop them.
* @return the incremented {@link VersionIdentifier}.
*/
public VersionIdentifier incrementSegment(int digitNumber, boolean keepLetters) {

cmd.quarkus=Tool commandlet for Quarkus (framework for cloud-native apps).
cmd.quarkus.detail=Quarkus is a Kubernetes-native Java framework for building cloud-native applications. Detailed documentation can be found at https://quarkus.io/
cmd.release=Performs a release of the project in your current working directory.
cmd.release.detail=The `release` commandlet automates a release of the project in your current working directory. It ensures there are no uncommitted changes, warns if you work on a fork, determines the current version of your project and derives the release version and the next development (SNAPSHOT) version for you to confirm. It then sets the release version, commits and tags it via git (as `release/«version»`), builds and deploys the project, sets the next development version, commits, and (after your confirmation) pushes the changes and the tag. Build and deploy options can be configured via the variable `MVN_RELEASE_OPTS` (default `clean deploy -Dchangelist= -Pdeploy`). You may also supply additional arguments as `ide release «args»` that will be passed to the maven build command.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It is great that you give such detailed help here.
However, for maintenance this is IMHO too detailed.
I would recommend to move the MVN_RELEASE_OPTS to the variables.adoc and keep the maven specific part out of here. In the last sentence you can replace maven build command with underlying build command (e.g. mvn).

@Override
public void commit(Path repository, String message) {

runGitCommand(repository, "commit", "-a", "-m", message);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I do not know what might come in the future but adding -a here is dangerous.
Typically you only want to commit what has already been added.
I would recommend to add a boolean option addAll so you do not also need to implement an add method here.
In the interface you may keep a variant without the option that delegates by passing false to addAll.
In your code you can then call it with true.

@Override
public void push(Path repository) {

runGitCommand(repository, "push", "--follow-tags");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

--follow-tags should better also be optional.

Comment on lines +69 to +72
public java.util.List<String> retrieveGitRemotes(Path repository) {

return java.util.Collections.emptyList();
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
public java.util.List<String> retrieveGitRemotes(Path repository) {
return java.util.Collections.emptyList();
}
public List<String> retrieveGitRemotes(Path repository) {
return Collections.emptyList();
}

Comment thread CHANGELOG.adoc
* https://github.com/devonfw/IDEasy/issues/797[#797]: Fix VSCode install on macOS
* https://github.com/devonfw/IDEasy/issues/1956[#1956]: Merging MAVEN_ARGS buggy
* https://github.com/devonfw/IDEasy/issues/1978[#1978]: Enhanced the quality status documentation
* https://github.com/devonfw/IDEasy/issues/1594[#1594]: Add release commandlet

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please move up 2 releases.

@@ -0,0 +1,2 @@
#!/bin/bash
echo java $*

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For simplicity, you could also remove dependencies.json since the goal of this test is to test ReleaseCommandlet and not Mvn so we do not have to include java at all.
Esp. we do not need a java.cmd command that is used in favour of java but only in Windows.
A kind of goal for test projects is to keep them as minimal as possible as long as they are realistic to test what the commandlet should do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commandlet ide sub-command devonfw-ide backward compatibility for devonfw-ide (regression) git git version management tool integration release related to release commandlet and releases of IDEasy

Projects

Status: 👀 In review

Development

Successfully merging this pull request may close these issues.

implement ReleaseCommandlet

4 participants