ci.maven
ci.maven copied to clipboard
Enhance Liberty Maven Plugin for CI integration
Outside of dev mode, atm, it isn't straightforward to use the Liberty Maven Plugin to package up what is needed or run tests whether locally or automatically integrated with a CI pipeline. See examples below.
Need to look at ways to improve this so it becomes straightforward to package up what you need and run tests using Liberty Maven Plugin for integrating with a CI pipeline.
There are different potential solutions e.g. an all-in-one goal or a new option for dev mode. The ultimate solution should be natural to Maven users and easy for developers to use.
Consider potential for all-in-one goal for users without LMP goals bound for test build, Docker build
The user who does not inherit from the LMP parent POM or even bind the LMP goals into the build lifecycle (e.g. the "ideal POM" user) has to use several goals in order to run integration tests.
Two examples:
- The appsody java-openliberty stack here uses a command like:
mvn clean liberty:create pre-integration-test liberty:install-feature liberty:start liberty:deploy failsafe:integration-test liberty:stop failsafe:verify
- The containerize guide WIP here from @gkwan-ibm has a similar sequence.
(A difference between the two is that the first example also copies dependencies into place - see #705, and also calls any goals bound to pre-integration-test).
Perhaps the "create" goal could do the part it does now (install server, create server and copy config over) plus the install-feature and deploy? Or maybe there are other ideas?
Note there's overlap between this and issues: https://github.com/OpenLiberty/ci.maven/issues/685 https://github.com/OpenLiberty/ci.maven/issues/667 (maybe we only need one, but I thought it was still helpful to write up the problem like this now.)
This issue should cover what is noted in #809 particularly the self-contained creation of a runnable jar.
One point on the command:
mvn clean liberty:create pre-integration-test liberty:install-feature liberty:start liberty:deploy failsafe:integration-test liberty:stop failsafe:verify
The reason for throwing the "pre-integration-test" phase in the middle of all those other goals is to reflect the fact that there might be some IT setup that our all-in-one-goals won't know about, because they require some type of app-specific setup, e.g. DB creation and population. This gives a phase to bind user-specific goals to.
I'm not saying this comment makes the solution any easier, just explaining the problem statement better.
@yeekangc @gkwan-ibm - what if we were to view this not as a whole separate goal but as a configuration of dev mode? E.g. what if I did: mvn -DquickTest liberty:dev
which caused the whole dev mode sequence to get executed, generate UT and IT reports, and stop the server, and then propagate back the IT exit status (0 vs. non-0)?
I remember liberty:dev
already support -DhotTests
but not exit the dev mode. Technically, I think it is not difficult for LMP to support, either mvn -DquickTest liberty:dev
, mvn -DquickTest liberty:run
, mvn liberty:verify
, or whatever interface. I prefer the interface should be obvious and simple to users.
It's not just the command-line interface that should be simple, though, but also the goal binding to the "lifecycle" created by all-in-one goals.
This is not just an implementation detail. These goals are configured by users, so they are part of the "POM interface", so to speak. We already have an all-in-one goal in the 'run' goal and a different one in the 'dev' goal impl. So I'm suggesting maybe keep this number from growing if possible and re-use the existing dev goal, to make the plugin behavior easier to understand.
I agree with @scottkurz. If we can achieve this through the existing dev
goal, that is better than adding another all-in-one goal.
As I am a user, I do not consider how the implementation will be, but I concern how the CLI make sense to me and what really be tested (the real packaged war at the apps
directory or loose app app.war.xml, which make sense to the users?)
if MST, use different approach
If you have a framework like MST/Testcontainers where you don't need a local install because you're running against Open Liberty in a container, you already have a simple approach (the most standard one): mvn verify
. I don't think it's worth trying to squeeze both this use case and an all-in-one test use case into one invocation... ultimately this will still require understanding from users and I thinking adding one more abstraction would be yet one more new invention to understand.
Yep, we studied MST and analyzed before. We agreed MST will use different approach. No need to consider MST in this issue.
@ericglau @sdaschner, any thoughts on the suggestion above to consider an option for dev mode to run tests in "headless" manner? To facilitate integration with automated test setup or CI pipeline. Even as a short hand for local runs.
Updated description to reflect the problems we want to solve per discussion with @NottyCode @gcharters.
Any solution should be natural to Maven users and should take into considerations what is typical/expected for a usual Maven lifecycle (e.g. mvn verify).
Additional user feedback on what is needed or will work will be useful too.
Hi there,
I like the approach of adding a "shortcut" of doing everything Liberty needs to do to run my app in one shot (I think we talked about this in the past).
From a cli perspective, I'd prefer a separate goal, simply because the lifecycle behaves differently to :dev
(stops Liberty again), and if I understand it correctly, it also doesn't really run as "dev mode" (listen to live code changes and reload) from a user perspective. Probably not much difference implementation-wise, but I think it makes more sense when you read the commands.
From a cli perspective, I'd prefer a separate goal, simply because the lifecycle behaves differently to
:dev
(stops Liberty again), and if I understand it correctly, it also doesn't really run as "dev mode" (listen to live code changes and reload)
To keep the number of all-in-one goals to two, we could also add an option to the 'run' goal, e.g: mvn -DtestRun liberty:run
Currently liberty:run and liberty:dev have two things in common: they are all-in-one goals, AND they keep the server running. If we introduce a flag that stops the server after tests are run, this seems to break the latter convention. Hence I think it makes more sense to have a separate goal.
If we think of these all-in-one goals as defining their own lifecycles (without defining a whole new packaging type or more advanced extension techniques), then my point is let's not create a third.
This design goal could be satisfied via a new liberty:test
where a new TestMojo extends RunMojo, and we refrain from proliferating with yet another all-in-one-style "lifecycle". If that seems to be a better UI, I guess I'm OK with that.
I do think we should document more clearly exactly which goals are called in each of 'dev' and 'run/test' more clearly in our doc. You can tease out this info from the dev mode doc but it should be documented like a Maven lifecycle is documented.
It's worth noting too I think that this really isn't about what's "natural" to Maven users.. . a more advanced Maven user at least knows how to construct the correct binding of goals to phases along with the right command line to do something like this. It's really the non-power-user that needs this simplified experience more. The all-in-one goals aren't really useful within a lifecycle. It could be confusing to have a mix of lifecycle-friendly goals and non-lifecycle, all-in-one goals, in one plugin. (One more reason I like to limit the number).
Currently to run integration tests in the CI mode I use the following Liberty plugin configuration:
It allows me just do all (create server, install features, deploy app and run test) in one go via: mvn clean verify
<!-- Enable liberty-maven plugin -->
<plugin>
<groupId>io.openliberty.tools</groupId>
<artifactId>liberty-maven-plugin</artifactId>
<version>3.3.4</version>
<executions>
<execution>
<id>install-feature</id>
<phase>prepare-package</phase>
<goals>
<goal>create</goal>
<goal>install-feature</goal>
</goals>
</execution>
<execution>
<id>start-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>test-start</goal>
<goal>deploy</goal>
</goals>
</execution>
<execution>
<id>stop-server</id>
<phase>post-integration-test</phase>
<goals> <goal>test-stop</goal> </goals>
</execution>
</executions>
<configuration>
<stripVersion>true</stripVersion>
</configuration>
</plugin>
Another use case overlapping this one is if I just wanted to build a runnable JAR out of a WAR packaged project (for some reason).
I'd have to do something like:
mvn package liberty:create liberty:install-feature liberty:deploy liberty:package -Dinclude=runnable
Perhaps that's enough of a special case it shouldn't get lumped into this issue but possibly worth considering.
I think we should reconsider the idea of a "skipServerStart" parameter flag for the 'run' goal.
This has been open for 4 years now without progress, and this would be a trivial change to implement. It is a bit weird conceptually "do a run without the server start" ... like "hamburger, hold the meat" :) But IMOH, it seems more maintainable to parameterize the existing 'run' goal vs. creating yet another (third) all-in-one goal.
Though this is a bit of a tangent on an already somewhat long and complicated discussion, let me note that the more all-in-one goals we have too, the harder it is to maintain consistency. E.g. when we recently added the new 'skipInstallFeature' behavior to dev mode, we didn't add the same to 'run'. We probably discussed it at the time, but now a few months removed, I don't see why it should be any different and why it wouldn't apply the same to 'run'.
DXDI 2024-01-31 UPDATE:
In the meeting a modest preference was expressed for defining a third goal but as a very thin extension of the 'run' goal. This would allow reuse of the implementation and would be simple to understand (the doc could, e.g. largely just link to the 'run' goal).
Perhaps 'liberty:bootstrap' ? I'm sure we could consider other names.
The next step is probably just to prototype this.
I so far can't find an incantation of this that works from my GitHub Actions build.
mvn package liberty:install-feature liberty:deploy liberty:run liberty:package -Dinclude=runnable
...
Downloaded from central: https://repo.maven.apache.org/maven2/io/openliberty/openliberty-kernel/24.0.0.7/openliberty-kernel-24.0.0.7.zip (15 MB at 50 MB/s)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.238 s
[INFO] Finished at: 2024-08-06T16:08:21Z
[INFO] ------------------------------------------------------------------------
Error: Failed to execute goal io.openliberty.tools:liberty-maven-plugin:3.10.3:install-feature (default-cli) on project WebTest: CWWKM2121E: Missing pre-installed assembly directory: /runner/_work/saz-max-proxy-web-test/saz-max-proxy-web-test/target/liberty/wlp.
And
mvn liberty:run liberty:package -Dinclude=runnable
Seems to have never come back. I had to kill the job. I guess that makes sense, it started in the foreground...
Anyway, for now, I'm just looking for some sequence that will do the trick from GitHub Actions.
I so far can't find an incantation of this that works from my GitHub Actions build.
It looks like you missed the 'create' goal, so maybe:
mvn package liberty:create liberty:install-feature liberty:deploy liberty:package -Dinclude=runnable
That seems to have done the trick, thanks.