diff --git a/.github/workflows/build-main.yml b/.github/workflows/build-main.yml
index 4eb7061a..a20e01c0 100644
--- a/.github/workflows/build-main.yml
+++ b/.github/workflows/build-main.yml
@@ -1,11 +1,9 @@
-name: Maven Build & Test (main)
+name: Publish snapshots from main
on:
push:
branches:
- main
- schedule:
- - cron: '0 0 * * *'
workflow_dispatch:
concurrency:
@@ -13,46 +11,140 @@ concurrency:
cancel-in-progress: true
jobs:
- build:
+ stage:
+ name: Build, test, and stage Maven artifacts
+ if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
checks: write
- timeout-minutes: 30
+ timeout-minutes: 45
steps:
- uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
- name: Set up JDK 25
uses: actions/setup-java@v5
with:
java-version: '25'
distribution: 'temurin'
cache: 'maven'
- server-id: central
- server-username: MAVEN_USERNAME
- server-password: MAVEN_CENTRAL_TOKEN
- gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
- gpg-passphrase: MAVEN_GPG_PASSPHRASE
- - name: Build with Maven
- run: ./mvnw --batch-mode -DskipTests package
- - name: Run tests
- id: tests
- continue-on-error: true
+ - name: Verify build
run: ./mvnw --batch-mode verify
- name: Build tests report
uses: dorny/test-reporter@v2
if: always()
with:
name: Maven Tests
- path: '**/target/surefire-reports/*.xml'
+ path: |
+ **/target/surefire-reports/*.xml
+ **/target/failsafe-reports/*.xml
reporter: java-junit
fail-on-error: true
- - name: Fail if tests failed
- if: steps.tests.outcome == 'failure'
- run: exit 1
- - name: Publish SNAPSHOT
- if: ${{ success() && github.event_name == 'push' }}
- run: ./mvnw --batch-mode -DskipTests -Ppublish-sonatype deploy
+ - name: Stage Maven artifacts
+ run: ./mvnw --batch-mode -DskipTests deploy -DaltDeploymentRepository=local::file:target/staging-deploy
+ - name: Archive Maven staging repository
+ run: tar -C target -czf target/maven-staging.tar.gz staging-deploy
+ - name: Upload Maven staging repository
+ uses: actions/upload-artifact@v7.0.0
+ with:
+ name: maven-staging
+ path: target/maven-staging.tar.gz
+ if-no-files-found: error
+ - name: Upload shaded CLI JAR
+ uses: actions/upload-artifact@v7.0.0
+ with:
+ name: single-jar
+ path: cli/target/roseau-[0-9]*.jar
+ if-no-files-found: error
+
+ assemble-jlink:
+ name: Assemble jlink ${{ matrix.platform }}
+ needs: stage
+ if: github.ref == 'refs/heads/main'
+ runs-on: ${{ matrix.runner }}
+ permissions:
+ contents: read
+ timeout-minutes: 30
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - runner: ubuntu-latest
+ platform: linux-x86_64
+ - runner: macos-15-intel
+ platform: osx-x86_64
+ - runner: macos-latest
+ platform: osx-aarch_64
+ - runner: windows-latest
+ platform: windows-x86_64
+ steps:
+ - uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+ - name: Set up JDK 25
+ uses: actions/setup-java@v5
+ with:
+ java-version: '25'
+ distribution: 'temurin'
+ cache: 'maven'
+ - name: Build CLI artifacts
+ shell: bash
+ run: ./mvnw --batch-mode -pl cli -am -DskipTests clean package
+ - name: Assemble jlink archive
+ shell: bash
+ run: ./mvnw --batch-mode -N jreleaser:assemble -Djreleaser.config.file=jreleaser.yml -Djreleaser.assemble.jlink.roseau-standalone.jdk.path="$JAVA_HOME" -Djreleaser.assemble.jlink.roseau-standalone.jdk.platform="${{ matrix.platform }}"
+ - name: Upload jlink archive
+ uses: actions/upload-artifact@v7.0.0
+ with:
+ name: jlink-${{ matrix.platform }}
+ path: target/jreleaser/assemble/roseau-standalone/jlink/*.zip
+ if-no-files-found: error
+
+ publish:
+ name: Publish Maven snapshots and rolling prerelease
+ needs:
+ - stage
+ - assemble-jlink
+ if: github.ref == 'refs/heads/main'
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ timeout-minutes: 30
+ steps:
+ - uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+ - name: Set up JDK 25
+ uses: actions/setup-java@v5
+ with:
+ java-version: '25'
+ distribution: 'temurin'
+ cache: 'maven'
+ - name: Download Maven staging repository
+ uses: actions/download-artifact@v5
+ with:
+ name: maven-staging
+ path: target
+ - name: Restore Maven staging repository
+ run: tar -C target -xzf target/maven-staging.tar.gz
+ - name: Download shaded CLI JAR
+ uses: actions/download-artifact@v5
+ with:
+ name: single-jar
+ path: cli/target
+ - name: Download jlink archives
+ uses: actions/download-artifact@v5
+ with:
+ pattern: jlink-*
+ merge-multiple: true
+ path: target/jreleaser/assemble/roseau-standalone/jlink
+ - name: Publish snapshots with JReleaser
+ run: ./mvnw --batch-mode -N jreleaser:full-release -Djreleaser.config.file=jreleaser.yml
env:
- MAVEN_USERNAME: ${{ secrets.NEXUS_USERNAME }}
- MAVEN_CENTRAL_TOKEN: ${{ secrets.NEXUS_PASSWORD }}
- MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+ JRELEASER_GITHUB_TOKEN: ${{ github.token }}
+ JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.GPG_PUBLIC_KEY }}
+ JRELEASER_GPG_SECRET_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
+ JRELEASER_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+ JRELEASER_NEXUS2_SNAPSHOT_DEPLOY_USERNAME: ${{ secrets.NEXUS_USERNAME }}
+ JRELEASER_NEXUS2_SNAPSHOT_DEPLOY_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 04592ff3..8713c62c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,60 +1,135 @@
-name: Publish release to Sonatype Central
+name: Publish release from tag
on:
- release:
- types: [ published ]
+ push:
+ tags:
+ - 'v*'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
jobs:
- verify:
- name: Verify on ${{ matrix.os }}
- runs-on: ${{ matrix.os }}
+ stage:
+ name: Build, test, and stage Maven artifacts
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ timeout-minutes: 45
+ steps:
+ - uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+ - name: Set up JDK 25
+ uses: actions/setup-java@v5
+ with:
+ java-version: '25'
+ distribution: 'temurin'
+ cache: 'maven'
+ - name: Verify build
+ run: ./mvnw --batch-mode verify
+ - name: Stage Maven artifacts
+ run: ./mvnw --batch-mode -DskipTests deploy -DaltDeploymentRepository=local::file:target/staging-deploy
+ - name: Archive Maven staging repository
+ run: tar -C target -czf target/maven-staging.tar.gz staging-deploy
+ - name: Upload Maven staging repository
+ uses: actions/upload-artifact@v7.0.0
+ with:
+ name: maven-staging
+ path: target/maven-staging.tar.gz
+ if-no-files-found: error
+ - name: Upload shaded CLI JAR
+ uses: actions/upload-artifact@v7.0.0
+ with:
+ name: single-jar
+ path: cli/target/roseau-[0-9]*.jar
+ if-no-files-found: error
+
+ assemble-jlink:
+ name: Assemble jlink ${{ matrix.platform }}
+ needs: stage
+ runs-on: ${{ matrix.runner }}
+ permissions:
+ contents: read
+ timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- - os: ubuntu-latest
- wrapper: ./mvnw
- - os: windows-latest
- wrapper: .\mvnw.cmd
- timeout-minutes: 30
- permissions:
- contents: read
+ - runner: ubuntu-latest
+ platform: linux-x86_64
+ - runner: macos-15-intel
+ platform: osx-x86_64
+ - runner: macos-latest
+ platform: osx-aarch_64
+ - runner: windows-latest
+ platform: windows-x86_64
steps:
- uses: actions/checkout@v6
- - name: Set up Java 25
+ with:
+ fetch-depth: 0
+ - name: Set up JDK 25
uses: actions/setup-java@v5
with:
java-version: '25'
distribution: 'temurin'
cache: 'maven'
- - name: Verify build
- run: ${{ matrix.wrapper }} --batch-mode verify
- env:
- # Ensure UTF-8 (Windows might not)
- MAVEN_OPTS: -Dfile.encoding=UTF-8
+ - name: Build CLI artifacts
+ shell: bash
+ run: ./mvnw --batch-mode -pl cli -am -DskipTests clean package
+ - name: Assemble jlink archive
+ shell: bash
+ run: ./mvnw --batch-mode -N jreleaser:assemble -Djreleaser.config.file=jreleaser.yml -Djreleaser.assemble.jlink.roseau-standalone.jdk.path="$JAVA_HOME" -Djreleaser.assemble.jlink.roseau-standalone.jdk.platform="${{ matrix.platform }}"
+ - name: Upload jlink archive
+ uses: actions/upload-artifact@v7.0.0
+ with:
+ name: jlink-${{ matrix.platform }}
+ path: target/jreleaser/assemble/roseau-standalone/jlink/*.zip
+ if-no-files-found: error
publish:
- name: Publish new version on Sonatype Central
+ name: Publish release with JReleaser
+ needs:
+ - stage
+ - assemble-jlink
runs-on: ubuntu-latest
- needs: verify
- if: ${{ needs.verify.result == 'success' }}
- timeout-minutes: 30
permissions:
- contents: read
+ contents: write
+ timeout-minutes: 30
steps:
- uses: actions/checkout@v6
- - uses: actions/setup-java@v5
+ with:
+ fetch-depth: 0
+ - name: Set up JDK 25
+ uses: actions/setup-java@v5
with:
java-version: '25'
distribution: 'temurin'
- server-id: central
- server-username: MAVEN_USERNAME
- server-password: MAVEN_CENTRAL_TOKEN
- gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
- gpg-passphrase: MAVEN_GPG_PASSPHRASE
- - name: Publish package
- run: ./mvnw --batch-mode -Ppublish-sonatype -DskipTests deploy
+ cache: 'maven'
+ - name: Download Maven staging repository
+ uses: actions/download-artifact@v7.0.0
+ with:
+ name: maven-staging
+ path: target
+ - name: Restore Maven staging repository
+ run: tar -C target -xzf target/maven-staging.tar.gz
+ - name: Download shaded CLI JAR
+ uses: actions/download-artifact@v7.0.0
+ with:
+ name: single-jar
+ path: cli/target
+ - name: Download jlink archives
+ uses: actions/download-artifact@v7.0.0
+ with:
+ pattern: jlink-*
+ merge-multiple: true
+ path: target/jreleaser/assemble/roseau-standalone/jlink
+ - name: Publish release with JReleaser
+ run: ./mvnw --batch-mode -N jreleaser:full-release -Djreleaser.config.file=jreleaser.yml
env:
- MAVEN_USERNAME: ${{ secrets.NEXUS_USERNAME }}
- MAVEN_CENTRAL_TOKEN: ${{ secrets.NEXUS_PASSWORD }}
- MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+ JRELEASER_GITHUB_TOKEN: ${{ github.token }}
+ JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.GPG_PUBLIC_KEY }}
+ JRELEASER_GPG_SECRET_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
+ JRELEASER_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+ JRELEASER_MAVENCENTRAL_RELEASE_DEPLOY_USERNAME: ${{ secrets.NEXUS_USERNAME }}
+ JRELEASER_MAVENCENTRAL_RELEASE_DEPLOY_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
diff --git a/cli/pom.xml b/cli/pom.xml
index ae984c44..3a05f8b6 100644
--- a/cli/pom.xml
+++ b/cli/pom.xml
@@ -15,6 +15,16 @@
jar
+
+
+ src/main/resources
+ false
+
+
+ src/main/version
+ true
+
+
org.apache.maven.plugins
@@ -24,6 +34,10 @@
org.apache.maven.plugins
maven-javadoc-plugin
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
org.apache.maven.plugins
maven-jar-plugin
@@ -37,27 +51,59 @@
org.apache.maven.plugins
- maven-assembly-plugin
+ maven-dependency-plugin
+ 3.8.1
+
+
+ copy-jlink-dependencies
+ package
+
+ copy-dependencies
+
+
+ runtime
+ ${project.build.directory}/jlink-jars
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.6.2
-
-
+ false
+ ${project.build.directory}/roseau-${project.version}.jar
+
+
+
io.github.alien.roseau.cli.RoseauCLI
- true
-
-
- true
-
-
-
- jar-with-dependencies
-
+
+ ${project.name}
+ ${project.version}
+ true
+
+
+
+
+
+ *:*
+
+ META-INF/*.SF
+ META-INF/*.DSA
+ META-INF/*.RSA
+
+
+
- make-assembly
+ shade-distribution
package
- single
+ shade
diff --git a/cli/src/main/java/io/github/alien/roseau/cli/RoseauCLI.java b/cli/src/main/java/io/github/alien/roseau/cli/RoseauCLI.java
index 027c6f39..f367336f 100644
--- a/cli/src/main/java/io/github/alien/roseau/cli/RoseauCLI.java
+++ b/cli/src/main/java/io/github/alien/roseau/cli/RoseauCLI.java
@@ -18,6 +18,8 @@
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
@@ -351,10 +353,30 @@ static void main(String[] args) {
}
static final class VersionProvider implements CommandLine.IVersionProvider {
+ private static final String VERSION_RESOURCE = "/roseau-version.txt";
+
@Override
public String[] getVersion() {
- String impl = Optional.ofNullable(Roseau.class.getPackage().getImplementationVersion()).orElse("0.6.0-SNAPSHOT");
- return new String[]{"Roseau " + impl};
+ return new String[]{"Roseau " + resolveVersion()};
+ }
+
+ static String resolveVersion() {
+ return Optional.ofNullable(RoseauCLI.class.getPackage().getImplementationVersion())
+ .or(VersionProvider::readVersionResource)
+ .orElse("unknown");
+ }
+
+ private static Optional readVersionResource() {
+ try (InputStream in = RoseauCLI.class.getResourceAsStream(VERSION_RESOURCE)) {
+ if (in == null) {
+ return Optional.empty();
+ }
+
+ String version = new String(in.readAllBytes(), StandardCharsets.UTF_8).trim();
+ return version.isEmpty() ? Optional.empty() : Optional.of(version);
+ } catch (IOException e) {
+ return Optional.empty();
+ }
}
}
}
diff --git a/cli/src/main/version/roseau-version.txt b/cli/src/main/version/roseau-version.txt
new file mode 100644
index 00000000..ad96e7cf
--- /dev/null
+++ b/cli/src/main/version/roseau-version.txt
@@ -0,0 +1 @@
+${project.version}
diff --git a/cli/src/test/java/io/github/alien/roseau/cli/RoseauCLITest.java b/cli/src/test/java/io/github/alien/roseau/cli/RoseauCLITest.java
index b33f8589..cd0fc08b 100644
--- a/cli/src/test/java/io/github/alien/roseau/cli/RoseauCLITest.java
+++ b/cli/src/test/java/io/github/alien/roseau/cli/RoseauCLITest.java
@@ -36,6 +36,14 @@ void no_mode() {
assertThat(exitCode).isEqualTo(ExitCode.ERROR.code());
}
+ @Test
+ void version_uses_build_version() {
+ var exitCode = cmd.execute("--version");
+
+ assertThat(out.toString()).contains("Roseau 0.6.0-SNAPSHOT");
+ assertThat(exitCode).isEqualTo(ExitCode.SUCCESS.code());
+ }
+
// --- Diffs --- //
@Test
void simple_source_diff() {
diff --git a/combinatorial/pom.xml b/combinatorial/pom.xml
index aac1085f..2d2bce17 100644
--- a/combinatorial/pom.xml
+++ b/combinatorial/pom.xml
@@ -13,6 +13,12 @@
roseau-combinatorial
Combinatorial Benchmark
+
+ true
+ true
+ true
+
+
@@ -91,4 +97,4 @@
4.7.7
-
\ No newline at end of file
+
diff --git a/core/pom.xml b/core/pom.xml
index b9059a6c..47aca55c 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -31,6 +31,10 @@
org.apache.maven.plugins
maven-javadoc-plugin
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
diff --git a/jreleaser.yml b/jreleaser.yml
new file mode 100644
index 00000000..8b7cc654
--- /dev/null
+++ b/jreleaser.yml
@@ -0,0 +1,89 @@
+project:
+ name: roseau
+ description: Fast and accurate API breaking change analysis of Java libraries
+ longDescription: |
+ Roseau detects binary and source breaking changes between two versions of a
+ Java library. It can compare JAR files or source trees and publish reports
+ suitable for local use, CI, and release automation.
+ authors:
+ - Thomas Degueule
+ - Jean-Remy Falleri
+ - Corentin Latappy
+ license: MIT
+ inceptionYear: 2023
+ stereotype: CLI
+ snapshot:
+ label: v{{projectVersion}}
+ links:
+ homepage: https://github.com/alien-tools/roseau
+ documentation: https://alien-tools.github.io/roseau/
+ bugTracker: https://github.com/alien-tools/roseau/issues
+ languages:
+ java:
+ groupId: io.github.alien-tools
+ artifactId: roseau-cli
+ version: 25
+ mainClass: io.github.alien.roseau.cli.RoseauCLI
+ multiProject: true
+
+release:
+ github:
+ owner: alien-tools
+ name: roseau
+ overwrite: true
+
+checksum:
+ algorithms:
+ - SHA-256
+
+signing:
+ active: ALWAYS
+ pgp:
+ active: ALWAYS
+ armored: true
+ verify: true
+
+deploy:
+ maven:
+ pomchecker:
+ failOnWarning: false
+ mavenCentral:
+ release-deploy:
+ active: RELEASE
+ url: https://central.sonatype.com/api/v1/publisher
+ applyMavenCentralRules: true
+ stagingRepositories:
+ - target/staging-deploy
+ nexus2:
+ snapshot-deploy:
+ active: SNAPSHOT
+ snapshotUrl: https://central.sonatype.com/repository/maven-snapshots/
+ applyMavenCentralRules: true
+ snapshotSupported: true
+ stagingRepositories:
+ - target/staging-deploy
+
+distributions:
+ roseau:
+ type: SINGLE_JAR
+ stereotype: CLI
+ artifacts:
+ - path: cli/target/roseau-{{projectVersion}}.jar
+
+assemble:
+ jlink:
+ roseau-standalone:
+ active: ALWAYS
+ exported: true
+ stereotype: CLI
+ executable: roseau
+ imageName: roseau-{{projectVersion}}
+ jdeps:
+ multiRelease: 25
+ ignoreMissingDeps: true
+ targets:
+ - cli/target/roseau-cli-{{projectVersion}}.jar
+ mainJar:
+ path: cli/target/roseau-cli-{{projectVersion}}.jar
+ jars:
+ - pattern: cli/target/jlink-jars/*.jar
diff --git a/maven-plugin/pom.xml b/maven-plugin/pom.xml
index 87481b93..113329a2 100644
--- a/maven-plugin/pom.xml
+++ b/maven-plugin/pom.xml
@@ -23,6 +23,14 @@
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
org.apache.maven.plugins
maven-plugin-plugin
diff --git a/pom.xml b/pom.xml
index 2afedc95..af1c882e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,6 +21,7 @@
25
+ 1.23.0
${java.version}
${java.version}
${java.version}
@@ -30,6 +31,12 @@
+
+ org.jreleaser
+ jreleaser-maven-plugin
+ ${jreleaser.version}
+ false
+
org.apache.maven.plugins
maven-compiler-plugin
@@ -66,6 +73,19 @@
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.4.0
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
org.apache.maven.plugins
maven-jar-plugin
@@ -75,53 +95,6 @@
-
-
- publish-sonatype
-
-
-
- org.sonatype.central
- central-publishing-maven-plugin
- 0.10.0
- true
-
- central
- roseau-combinatorial
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
- 3.4.0
-
-
- attach-sources
-
- jar-no-fork
-
-
-
-
-
- org.apache.maven.plugins
- maven-gpg-plugin
- 3.2.8
-
-
- sign-artifacts
- verify
-
- sign
-
-
-
-
-
-
-
-
-
diff --git a/src/jreleaser/assemblers/roseau-standalone/jlink/LICENSE b/src/jreleaser/assemblers/roseau-standalone/jlink/LICENSE
new file mode 100644
index 00000000..2f14d305
--- /dev/null
+++ b/src/jreleaser/assemblers/roseau-standalone/jlink/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Roseau
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/src/jreleaser/assemblers/roseau-standalone/jlink/README.md.tpl b/src/jreleaser/assemblers/roseau-standalone/jlink/README.md.tpl
new file mode 100644
index 00000000..3f499cf9
--- /dev/null
+++ b/src/jreleaser/assemblers/roseau-standalone/jlink/README.md.tpl
@@ -0,0 +1,16 @@
+# Roseau {{projectVersion}}
+
+This archive contains the standalone Roseau CLI together with a bundled Java runtime.
+No separate Java installation is required.
+
+## Usage
+
+- macOS and Linux: `bin/{{distributionExecutable}} --help`
+- Windows: `bin\{{distributionExecutable}}.bat --help`
+
+## Examples
+
+- Show the CLI version: `bin/{{distributionExecutable}} --version`
+- Compare two libraries: `bin/{{distributionExecutable}} --diff --v1 old.jar --v2 new.jar`
+
+Use the shaded JAR release instead if you need a JVM-based fallback for an unsupported platform.