From 208db654781459ec8313e90a33ded8ee61460db2 Mon Sep 17 00:00:00 2001 From: Lutz Wrage Date: Wed, 2 Sep 2026 10:56:26 -0400 Subject: [PATCH] Report the OSATE and language-server build in osate-cli help MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #5. `osate-cli help` now reports what the CLI was built from: osate-cli 0.1.0 language server 0.1.0.v20260902-1320 (7fbfec9) OSATE 2.19.0.vfinal (4256148) None of this is discoverable at runtime, which is what shaped the design. OSATE bundles carry independent versions — org.osate.aadl2 is 6.1.1, not 2.19.0 — and no bundle manifest records a commit, so both OSATE values have to be baked in. scripts/build-test-release is the only place that knows the osate2 gitlink and the built language-server bundle version, so it supplies all four values and Maven filters them into version.properties beside the existing version. osate.commit is the gitlink rather than the submodule's HEAD: it is the reviewed pin, and the build already refuses to proceed when the two disagree. --version is deliberately untouched. Its output is compared for exact equality by CliEndToEndIT and parsed by the packaging scripts' --expect-version check, so versionLine() stays one line and a new versionDetail() carries the provenance into help() only. A test now pins that, because the temptation to append to the version line is obvious and the breakage would be remote. ls.commit gains a -dirty suffix when the tree had uncommitted changes. Without it the commit would appear to identify code that is not what was compiled; the superproject is allowed to be dirty during development, unlike the submodule, so marking is better than refusing. Both the suffix and the commit it decorates are recorded before any build runs, so they describe the sources that went in. build-provenance.properties gets the same treatment for tooling.commit, which had the identical problem. Two release guards, since the values only appear when the build goes through the script: - build-release-artifacts.sh refuses to package a distribution reporting 'unknown', so a hand-built CLI cannot be released claiming a provenance it does not have. - It also refuses one whose recorded osate.commit disagrees with the current gitlink, extending an invariant the source build already enforces to the artifact. A dirty tree only warns there. The -dirty suffix is already visible in the jar and in help, so the artifact is not misleading, and failing would block the local packaging smoke tests that packaging/README.md documents. abbreviate() shortens only the leading hex run, so -dirty displays as 7fbfec9-dirty rather than losing the marker that says the value cannot be trusted, and a placeholder like 'unknown' is returned untouched instead of being truncated into something that reads like a commit. Incidentally removes a Maven invocation: osate.version is now read from the pinned submodule's pom, which the --skip-osate precondition check was already doing separately. Verified: --version unchanged; help shows all three lines; the guards accept a correct dist, reject an unknown-provenance one, and reject a gitlink mismatch; VersionTest covers both the supplied and unsupplied provenance paths (it skips one or the other depending on how the build ran, and both were exercised). Documented in OSATE-CLI.md with four new manual-test cases. --- osate-cli/OSATE-CLI.md | 46 +++++++++- osate-cli/osate-cli/manual-test.md | 4 + .../main/java/org/osate/cli/ArgParser.java | 26 +++++- .../src/main/java/org/osate/cli/Version.java | 89 ++++++++++++++++--- .../org/osate/cli/version.properties | 10 +++ .../java/org/osate/cli/ArgParserTest.java | 32 +++++++ .../test/java/org/osate/cli/VersionTest.java | 49 ++++++++++ .../scripts/build-release-artifacts.sh | 10 +++ osate-cli/packaging/scripts/common.sh | 51 +++++++++++ osate-cli/pom.xml | 10 +++ scripts/build-test-release | 51 ++++++++--- 11 files changed, 347 insertions(+), 31 deletions(-) diff --git a/osate-cli/OSATE-CLI.md b/osate-cli/OSATE-CLI.md index 930821e..a4ce3c3 100644 --- a/osate-cli/OSATE-CLI.md +++ b/osate-cli/OSATE-CLI.md @@ -80,9 +80,15 @@ osate-cli help osate-cli -h | --help ``` -Prints usage. The long form (`help`) prints the version banner, followed by the full -description of every command and exit codes; the short form (`-h`/`--help`) prints just -the synopsis lines. +Prints usage. The long form (`help`) prints the version banner and the build it came +from, followed by the full description of every command and exit codes; the short form +(`-h`/`--help`) prints just the synopsis lines. + +```text +osate-cli 0.1.0 + language server 0.1.0.v20260902-1320 (7fbfec9) + OSATE 2.19.0.vfinal (4256148) +``` ### version @@ -90,7 +96,8 @@ the synopsis lines. osate-cli -v | --version ``` -Prints `osate-cli ` and exits 0. +Prints `osate-cli ` and exits 0. Exactly one line, with nothing after the +version, so it stays parseable; use `help` for the build provenance. The version is declared in exactly one place: the `` property of `osate-cli/pom.xml`. Maven filters it into `org/osate/cli/version.properties` inside @@ -98,6 +105,37 @@ The version is declared in exactly one place: the `` property of release tarballs, `.deb`, `.rpm`, and Homebrew formula. The version reported here is therefore always the version of the package the CLI was installed from. +### Build provenance + +`help` also reports the bundled language server and the OSATE it was built against, +because the CLI's own version says nothing about either, and most behaviour comes from +them: + +| Key in `version.properties` | Meaning | +| --- | --- | +| `ls.version` | Bundle version of the bundled language server, e.g. `0.1.0.v20260902-1320` | +| `ls.commit` | Commit of the `osate/aadl-tooling` repository it was built from | +| `osate.version` | OSATE version, e.g. `2.19.0.vfinal` | +| `osate.commit` | The reviewed `osate2` gitlink it was built against | + +None of these can be discovered at runtime. OSATE bundles carry independent versions +(`org.osate.aadl2` is 6.1.1, not 2.19.0) and no bundle manifest records a commit, so +`scripts/build-test-release` supplies all four and Maven filters them into the jar +alongside the version. + +A build that bypasses that script — a bare `mvn -f osate-cli/pom.xml verify` — reports +`unknown` for all four. That is deliberate, so a hand-built CLI does not claim a +provenance it does not have; `build-release-artifacts.sh` refuses to package a +distribution that reports `unknown`, and also refuses one whose `osate.commit` disagrees +with the current gitlink. + +`ls.commit` gains a `-dirty` suffix when the working tree had uncommitted changes, since +the commit alone would otherwise appear to identify code that was not what got compiled. +Packaging warns about it rather than failing, so local packaging tests still work. + +Commits are abbreviated to seven characters in `help`; `version.properties` keeps them in +full for anything parsing the jar. + ### project The local project commands treat the current working directory as a workspace. Projects diff --git a/osate-cli/osate-cli/manual-test.md b/osate-cli/osate-cli/manual-test.md index 48b7b08..77a7511 100644 --- a/osate-cli/osate-cli/manual-test.md +++ b/osate-cli/osate-cli/manual-test.md @@ -167,6 +167,10 @@ process in its own process tree. | 1.4a | `osate-cli -v` | exit 0; `osate-cli ` on stdout | | 1.4b | `osate-cli --version` | exit 0; same output as 1.4a | | 1.4c | `osate-cli -v` from an installed package | version matches the installed Homebrew/deb/rpm package version (`brew list --versions osate-cli`, `dpkg -s osate-cli`, or `rpm -q osate-cli`) | +| 1.4d | `osate-cli help` | lines 2-3 report the build: ` language server ()` and ` OSATE ()`, both indented | +| 1.4e | `osate-cli --version` | still exactly one line; provenance appears only in `help` | +| 1.4f | `osate-cli help` from an installed package | neither provenance line says `unknown`; a released package always records what it was built from | +| 1.4g | `osate-cli help` from a locally built dist with a dirty tree | the language-server commit carries a `-dirty` suffix | | 1.5 | `osate-cli c1 bogus` | exit 2; "missing -p " or unknown-command error | | 1.6 | `osate-cli c1 -p 1 bogus` | exit 2; "unknown command: bogus" | | 1.7 | `osate-cli c1 -p abc ping` | exit 2; "-p/--port must be an integer in 1..65535: abc" | diff --git a/osate-cli/osate-cli/src/main/java/org/osate/cli/ArgParser.java b/osate-cli/osate-cli/src/main/java/org/osate/cli/ArgParser.java index 3f34dc4..a755e38 100644 --- a/osate-cli/osate-cli/src/main/java/org/osate/cli/ArgParser.java +++ b/osate-cli/osate-cli/src/main/java/org/osate/cli/ArgParser.java @@ -364,13 +364,35 @@ private static String projectUsage() { return "usage: project [args...]"; } - /** Version banner printed by {@code -v}/{@code --version} and atop the help text. */ + /** + * Version banner printed by {@code -v}/{@code --version} and atop the help text. + * + *

Deliberately a single line with nothing after the version: the assembled-CLI + * integration test compares {@code --version} output for exact equality, and the + * packaging scripts' {@code --expect-version} check parses it. Build provenance goes + * in {@link #versionDetail()}, which only {@link #help()} prints. + */ public static String versionLine() { return "osate-cli " + Version.get(); } + /** + * Indented provenance lines describing what this CLI was built from. + * + *

Answers "which OSATE is this?", which the version alone does not: the behaviour + * a user sees comes mostly from the bundled language server and the OSATE underneath + * it. Commits are abbreviated for reading; {@code version.properties} inside the jar + * keeps them in full. + */ + public static String versionDetail() { + return " language server " + Version.languageServerVersion() + " (" + + Version.abbreviate(Version.languageServerCommit(), 7) + ")\n" + + " OSATE " + Version.osateVersion() + " (" + + Version.abbreviate(Version.osateCommit(), 7) + ")"; + } + public static String help() { - return versionLine() + "\n\n" + usage() + "\n" + """ + return versionLine() + "\n" + versionDetail() + "\n\n" + usage() + "\n" + """ osate-cli is a command-line client for the OSATE AADL language server. Remote commands talk to a long-lived workspace server (one per workspace) over a TCP diff --git a/osate-cli/osate-cli/src/main/java/org/osate/cli/Version.java b/osate-cli/osate-cli/src/main/java/org/osate/cli/Version.java index 4aba166..ff27b48 100644 --- a/osate-cli/osate-cli/src/main/java/org/osate/cli/Version.java +++ b/osate-cli/osate-cli/src/main/java/org/osate/cli/Version.java @@ -27,7 +27,7 @@ import java.util.Properties; /** - * Reports the osate-cli release version. + * Reports the osate-cli release version and what it was built against. * *

The version is declared once, in the {@code } property of * {@code osate-cli/pom.xml}. Maven resource filtering writes it into @@ -36,6 +36,12 @@ * rpm, and Homebrew packages. The version reported here therefore always matches the * package the CLI was installed from. * + *

The same resource carries the bundled language server's version and commit and the + * OSATE version and commit. None of those can be discovered at runtime: OSATE bundles + * carry independent versions ({@code org.osate.aadl2} is 6.1.1, not 2.19.0) and no + * bundle manifest records a commit, so {@code scripts/build-test-release} bakes them in. + * A build that bypasses that script reports {@link #UNKNOWN_PROVENANCE} for them. + * *

A properties resource is used rather than the jar manifest's * {@code Implementation-Version} because the resource is also present when running from * {@code target/classes} (tests and IDE launches), and because manifest values are line @@ -46,9 +52,18 @@ public final class Version { /** Reported when the filtered resource is missing, e.g. from a hand-assembled classpath. */ public static final String UNKNOWN = "0.0.0-dev"; + /** Reported for build provenance that the build did not supply. */ + public static final String UNKNOWN_PROVENANCE = "unknown"; + private static final String RESOURCE = "/org/osate/cli/version.properties"; - private static final String VERSION = load(); + private static final Properties PROPS = load(); + + private static final String VERSION = read("version", UNKNOWN); + private static final String LS_VERSION = read("ls.version", UNKNOWN_PROVENANCE); + private static final String LS_COMMIT = read("ls.commit", UNKNOWN_PROVENANCE); + private static final String OSATE_VERSION = read("osate.version", UNKNOWN_PROVENANCE); + private static final String OSATE_COMMIT = read("osate.commit", UNKNOWN_PROVENANCE); private Version() { } @@ -58,18 +73,70 @@ public static String get() { return VERSION; } - private static String load() { + /** Bundle version of the language server this CLI ships, e.g. {@code 0.1.0.v20260902-1313}. */ + public static String languageServerVersion() { + return LS_VERSION; + } + + /** Commit of this repository that the bundled language server was built from. */ + public static String languageServerCommit() { + return LS_COMMIT; + } + + /** OSATE version the language server was built against, e.g. {@code 2.19.0.vfinal}. */ + public static String osateVersion() { + return OSATE_VERSION; + } + + /** The reviewed {@code osate2} gitlink the language server was built against. */ + public static String osateCommit() { + return OSATE_COMMIT; + } + + /** Whether every provenance value was supplied by the build. */ + public static boolean hasCompleteProvenance() { + return !UNKNOWN.equals(VERSION) && !UNKNOWN_PROVENANCE.equals(LS_VERSION) + && !UNKNOWN_PROVENANCE.equals(LS_COMMIT) && !UNKNOWN_PROVENANCE.equals(OSATE_VERSION) + && !UNKNOWN_PROVENANCE.equals(OSATE_COMMIT); + } + + /** + * Shortens a commit for display, keeping any trailing marker. + * + *

Only the leading hexadecimal run is shortened, so {@code -dirty} becomes + * {@code 7fbfec9-dirty} rather than losing the suffix that says the value cannot be + * trusted, and a non-commit placeholder like {@code unknown} is returned untouched + * instead of being truncated into something that looks like a commit. + */ + public static String abbreviate(String commit, int length) { + if (commit == null) { + return null; + } + var hex = 0; + while (hex < commit.length() && Character.digit(commit.charAt(hex), 16) >= 0) { + hex++; + } + if (hex <= length) { + return commit; + } + return commit.substring(0, length) + commit.substring(hex); + } + + private static Properties load() { + var props = new Properties(); try (InputStream in = Version.class.getResourceAsStream(RESOURCE)) { - if (in == null) { - return UNKNOWN; + if (in != null) { + props.load(in); } - var props = new Properties(); - props.load(in); - var version = props.getProperty("version", "").trim(); - // An unfiltered resource still holds the literal Maven expression. - return version.isEmpty() || version.startsWith("${") ? UNKNOWN : version; } catch (IOException e) { - return UNKNOWN; + // Fall through to the empty properties; every value then reports its fallback. } + return props; + } + + private static String read(String key, String fallback) { + var value = PROPS.getProperty(key, "").trim(); + // An unfiltered resource still holds the literal Maven expression. + return value.isEmpty() || value.startsWith("${") ? fallback : value; } } diff --git a/osate-cli/osate-cli/src/main/resources/org/osate/cli/version.properties b/osate-cli/osate-cli/src/main/resources/org/osate/cli/version.properties index 02831b8..d1bb63e 100644 --- a/osate-cli/osate-cli/src/main/resources/org/osate/cli/version.properties +++ b/osate-cli/osate-cli/src/main/resources/org/osate/cli/version.properties @@ -22,3 +22,13 @@ # Generated from the property in osate-cli/pom.xml by Maven resource # filtering. Do not edit the version by hand; bump instead. version=${project.version} + +# What this CLI was built against. Neither of the OSATE values can be recovered at +# runtime: OSATE bundles carry independent versions (org.osate.aadl2 is 6.1.1, not +# 2.19.0) and no bundle manifest records a commit, so they have to be baked in +# here. scripts/build-test-release supplies them; a build that does not go through +# it leaves them 'unknown'. +ls.version=${aadl.ls.version} +ls.commit=${aadl.ls.commit} +osate.version=${osate.version} +osate.commit=${osate.commit} diff --git a/osate-cli/osate-cli/src/test/java/org/osate/cli/ArgParserTest.java b/osate-cli/osate-cli/src/test/java/org/osate/cli/ArgParserTest.java index ecbb125..6fa2069 100644 --- a/osate-cli/osate-cli/src/test/java/org/osate/cli/ArgParserTest.java +++ b/osate-cli/osate-cli/src/test/java/org/osate/cli/ArgParserTest.java @@ -105,6 +105,30 @@ void versionLineReportsPackagedVersion() { assertEquals("osate-cli " + Version.get(), ArgParser.versionLine()); } + /** + * {@code --version} prints this and nothing else, so it must stay one line. The + * assembled-CLI test compares that output for exact equality and the packaging + * scripts parse it, so appending build provenance here would break both. Provenance + * belongs in {@code versionDetail()}, which only {@code help()} prints. + */ + @Test + void versionLineStaysASingleLine() { + assertEquals(1, ArgParser.versionLine().lines().count()); + } + + @Test + void versionDetailReportsWhatTheCliWasBuiltFrom() { + var detail = ArgParser.versionDetail(); + + assertTrue(detail.contains("language server"), () -> detail); + assertTrue(detail.contains("OSATE"), () -> detail); + assertTrue(detail.contains(Version.languageServerVersion()), () -> detail); + assertTrue(detail.contains(Version.osateVersion()), () -> detail); + assertTrue(detail.contains(Version.abbreviate(Version.osateCommit(), 7)), () -> detail); + // Every line indented, so the banner stays the only flush-left line in help. + assertTrue(detail.lines().allMatch(line -> line.startsWith(" ")), () -> detail); + } + @Test void helpStartsWithVersionBanner() { var help = ArgParser.help(); @@ -114,6 +138,14 @@ void helpStartsWithVersionBanner() { assertTrue(ArgParser.usage().contains("osate-cli -v | --version")); } + @Test + void helpIncludesBuildProvenanceUnderTheBanner() { + var lines = ArgParser.help().lines().toList(); + + assertEquals(ArgParser.versionLine(), lines.get(0)); + assertEquals(ArgParser.versionDetail(), String.join("\n", lines.subList(1, 3))); + } + @Test void helpMatchesLocalAndLanguageServerDispatch() { var help = ArgParser.help(); diff --git a/osate-cli/osate-cli/src/test/java/org/osate/cli/VersionTest.java b/osate-cli/osate-cli/src/test/java/org/osate/cli/VersionTest.java index 2a82700..4a131fb 100644 --- a/osate-cli/osate-cli/src/test/java/org/osate/cli/VersionTest.java +++ b/osate-cli/osate-cli/src/test/java/org/osate/cli/VersionTest.java @@ -23,7 +23,10 @@ package org.osate.cli; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assumptions.assumeTrue; import org.junit.jupiter.api.Test; @@ -48,4 +51,50 @@ void matchesVersionDeclaredInPom() { void isResolvedNotFallback() { assertNotEquals(Version.UNKNOWN, Version.get()); } + + /** + * The provenance keys must resolve to something, even in a standalone reactor build + * that supplies no values. A literal {@code ${...}} here would mean the keys were + * added to the resource but not declared as pom properties, which would otherwise + * surface as raw Maven expressions printed in {@code osate-cli help}. + */ + @Test + void provenanceIsNeverAnUnfilteredExpression() { + for (var value : new String[] { Version.languageServerVersion(), Version.languageServerCommit(), + Version.osateVersion(), Version.osateCommit() }) { + assertNotNull(value); + assertFalse(value.isBlank(), "provenance value is blank"); + assertFalse(value.startsWith("${"), () -> "unfiltered provenance value: " + value); + } + } + + /** + * A standalone {@code mvn -f osate-cli/pom.xml verify} supplies no provenance, so the + * pom defaults must say so rather than report a real-looking value. The release path + * asserts the opposite; see {@code packaging/scripts/build-release-artifacts.sh}. + */ + @Test + void provenanceReportsUnknownWhenTheBuildSuppliesNothing() { + assumeTrue(Version.UNKNOWN_PROVENANCE.equals(Version.osateCommit()), + "this build supplied provenance, so there is nothing to check here"); + assertFalse(Version.hasCompleteProvenance()); + } + + @Test + void abbreviateShortensTheCommitAndKeepsAnyMarker() { + assertEquals("4256148", Version.abbreviate("425614884eaf14312141fbdd3a393ba54ff34b23", 7)); + + // The -dirty marker says the commit does not describe what was built, so it has + // to survive; dropping it would turn an untrustworthy value into a trustworthy + // looking one. Local builds are the common case here. + assertEquals("7fbfec9-dirty", + Version.abbreviate("7fbfec98e4f2d78fff9ebf8dca7c866cbad8029b-dirty", 7)); + + // Not a commit at all: returning it untouched keeps it obviously not a commit. + assertEquals("unknown", Version.abbreviate("unknown", 7)); + + // Already short enough, even though every character happens to be hex. + assertEquals("abc", Version.abbreviate("abc", 7)); + assertNull(Version.abbreviate(null, 7)); + } } diff --git a/osate-cli/packaging/scripts/build-release-artifacts.sh b/osate-cli/packaging/scripts/build-release-artifacts.sh index 0826f83..43855ae 100755 --- a/osate-cli/packaging/scripts/build-release-artifacts.sh +++ b/osate-cli/packaging/scripts/build-release-artifacts.sh @@ -128,7 +128,17 @@ OSATE_CLI_VERSION=$(version_from_dist "$dist_dir") if [ -n "$expect_version" ] && [ "$expect_version" != "$OSATE_CLI_VERSION" ]; then die "dist reports version $OSATE_CLI_VERSION, but --expect-version is $expect_version" fi + +# Refuse to package a CLI that cannot say which OSATE it came from. Compared against +# the gitlink rather than the submodule's HEAD: the gitlink is the reviewed pin, and +# it is readable here even when the submodule is not checked out. +osate_gitlink=$(git -C "$repo_root" ls-files --stage osate2 2>/dev/null | + awk '$1 == "160000" { print $2 }') +require_release_provenance "$dist_dir" "$osate_gitlink" + echo "Packaging $OSATE_CLI_PACKAGE_NAME $OSATE_CLI_VERSION (from $dist_dir/osate-cli.jar)" +echo " language server $(provenance_from_dist "$dist_dir" ls.version) ($(provenance_from_dist "$dist_dir" ls.commit))" +echo " OSATE $(provenance_from_dist "$dist_dir" osate.version) ($(provenance_from_dist "$dist_dir" osate.commit))" downloads_dir="$output_dir/downloads" staging_dir="$output_dir/staging" diff --git a/osate-cli/packaging/scripts/common.sh b/osate-cli/packaging/scripts/common.sh index 14d2e41..a58991c 100644 --- a/osate-cli/packaging/scripts/common.sh +++ b/osate-cli/packaging/scripts/common.sh @@ -69,6 +69,57 @@ version_from_dist() { printf '%s\n' "$version" } +# Reads one build-provenance key from the version.properties resource in a built jar. +provenance_from_dist() { + local dist_dir=$1 + local key=$2 + local jar="$dist_dir/osate-cli.jar" + + [ -f "$jar" ] || die "osate-cli.jar not found in $dist_dir" + require_command unzip + unzip -p "$jar" org/osate/cli/version.properties 2>/dev/null | + awk -F= -v k="^$key=" '$0 ~ k { gsub(/[[:space:]]/, "", $2); print $2; exit }' +} + +# A release must be able to say which OSATE it was built from, and must say so +# truthfully. Both checks matter because the values are only supplied when the build +# goes through scripts/build-test-release: packaging a CLI built any other way would +# otherwise ship 'unknown', and nothing would catch a recorded OSATE commit that +# disagrees with the submodule pin actually built. +require_release_provenance() { + local dist_dir=$1 + local expected_osate_commit=${2:-} + local key value + + for key in ls.version ls.commit osate.version osate.commit; do + value=$(provenance_from_dist "$dist_dir" "$key") + [ -n "$value" ] || die "missing $key in osate-cli.jar; build via scripts/build-test-release" + case "$value" in + unknown | '${'*) + die "osate-cli.jar reports $key=$value; a release must record real provenance. Build via scripts/build-test-release, which supplies it." + ;; + esac + done + + # A warning, not a failure: the -dirty suffix is recorded in the jar and shown by + # 'osate-cli help', so the artifact is not misleading, and refusing would block the + # local packaging smoke tests in packaging/README.md. A CI release builds from a + # clean checkout and never reaches this. + value=$(provenance_from_dist "$dist_dir" ls.commit) + case "$value" in + *-dirty) + warn "packaging a CLI built from a dirty tree (ls.commit=$value)" + ;; + esac + + if [ -n "$expected_osate_commit" ]; then + value=$(provenance_from_dist "$dist_dir" osate.commit) + if [ "$value" != "$expected_osate_commit" ]; then + die "osate-cli.jar records osate.commit=$value but the osate2 gitlink is $expected_osate_commit" + fi + fi +} + # Reads the version recorded next to the artifacts by build-release-artifacts.sh. version_from_artifacts() { local artifacts_dir=$1 diff --git a/osate-cli/pom.xml b/osate-cli/pom.xml index 9c86e65..ea119a4 100644 --- a/osate-cli/pom.xml +++ b/osate-cli/pom.xml @@ -46,6 +46,16 @@ Keep it a plain release version: rpm forbids '-' in Version, so a '-SNAPSHOT' suffix would not survive packaging. --> 0.1.0 + + unknown + unknown + unknown + unknown 21 UTF-8 2.11.0 diff --git a/scripts/build-test-release b/scripts/build-test-release index 80664a2..537d309 100755 --- a/scripts/build-test-release +++ b/scripts/build-test-release @@ -114,6 +114,24 @@ if [[ -n $(git -C "${osate_dir}" status --porcelain) ]]; then exit 1 fi +# Recorded before anything is built, so it describes the sources that went in. +# The superproject is allowed to be dirty during development, unlike the +# submodule, so mark it rather than refusing: a commit alone would otherwise +# claim to identify code that is not what was compiled. +tooling_commit=$(git -C "${repo_root}" rev-parse HEAD) +if [[ -n $(git -C "${repo_root}" status --porcelain) ]]; then + tooling_commit="${tooling_commit}-dirty" +fi + +osate_version=$(sed -n 's#.*\(.*\).*#\1#p' \ + "${osate_main_pom}" | head -n 1) +if [[ -z "${osate_version}" ]]; then + echo "Could not read from:" >&2 + echo " ${osate_main_pom}" >&2 + echo "The OSATE build layout changed; update this script." >&2 + exit 1 +fi + if [[ "${skip_osate}" == true ]]; then echo "Reusing existing OSATE build" @@ -129,22 +147,13 @@ if [[ "${skip_osate}" == true ]]; then exit 1 fi - osate_platform_version=$(sed -n 's#.*\(.*\).*#\1#p' \ - "${osate_main_pom}" | head -n 1) - if [[ -z "${osate_platform_version}" ]]; then - echo "Could not read from:" >&2 - echo " ${osate_main_pom}" >&2 - echo "The OSATE build layout changed; update this script." >&2 - exit 1 - fi - # -N keeps this to the aggregator pom; resolving the modules would need the # very OSATE artifacts this check is about to look for. local_repo=$(mvn -q -N -f "${repo_root}/pom.xml" help:evaluate \ -Dexpression=settings.localRepository -DforceStdout) - osate_platform_dir="${local_repo}/org/osate/osate2-platform/${osate_platform_version}" + osate_platform_dir="${local_repo}/org/osate/osate2-platform/${osate_version}" if ! compgen -G "${osate_platform_dir}/*.target" >/dev/null; then - echo "OSATE target definition org.osate:osate2-platform:${osate_platform_version} is not installed at:" >&2 + echo "OSATE target definition org.osate:osate2-platform:${osate_version} is not installed at:" >&2 echo " ${osate_platform_dir}" >&2 echo "The language-server reactor resolves it from the Maven local repository," >&2 echo "so the OSATE build must run with 'install'. Run without --skip-osate." >&2 @@ -228,9 +237,25 @@ if [[ "${skip_cli}" == true ]]; then else echo "Building OSATE CLI" + # The language-server bundle version is only knowable after its build, and the + # osate2 gitlink is only knowable here, so the CLI reactor cannot derive either + # on its own. The underscore in the glob keeps org.osate.aadl.ls.tests out. + ls_bundle=$(find "${plugins_dir}" -name 'org.osate.aadl.ls_*.jar' -exec basename {} \; | head -n 1) + ls_version=${ls_bundle#org.osate.aadl.ls_} + ls_version=${ls_version%.jar} + if [[ -z "${ls_version}" ]]; then + echo "Could not determine the language-server bundle version from:" >&2 + echo " ${plugins_dir}" >&2 + exit 1 + fi + mvn \ -T6 \ -f "${repo_root}/osate-cli/pom.xml" \ + -Daadl.ls.version="${ls_version}" \ + -Daadl.ls.commit="${tooling_commit}" \ + -Dosate.version="${osate_version}" \ + -Dosate.commit="${expected_osate_sha}" \ verify fi @@ -259,14 +284,12 @@ fi tooling_version=$(mvn -q -f "${repo_root}/pom.xml" help:evaluate \ -Dexpression=project.version -DforceStdout) -osate_version=$(mvn -q -f "${osate_dir}/pom.xml" help:evaluate \ - -Dexpression=project.version -DforceStdout) cli_version=$(mvn -q -f "${repo_root}/osate-cli/pom.xml" help:evaluate \ -Dexpression=project.version -DforceStdout) mkdir -p "${provenance_dir}" { - printf 'tooling.commit=%s\n' "$(git -C "${repo_root}" rev-parse HEAD)" + printf 'tooling.commit=%s\n' "${tooling_commit}" printf 'tooling.version=%s\n' "${tooling_version}" printf 'osate.commit=%s\n' "${actual_osate_sha}" printf 'osate.gitlink=%s\n' "${expected_osate_sha}"