Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
442eb4398c
|
||
|
|
3aa728d88a
|
||
|
|
51ab908b11 | ||
|
|
3474b0c188
|
||
|
|
b12cadfc75 |
No files matched your search
@@ -4,6 +4,10 @@ Following [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and [Semantic
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- QBit metadata now reports the Maven artifact version, including release versions, from a filtered build resource.
|
||||
|
||||
### Added
|
||||
|
||||
- Complete host-neutral in-app help bundle with live metadata references and a core help coverage gate.
|
||||
@@ -42,6 +46,8 @@ Following [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and [Semantic
|
||||
|
||||
### Changed
|
||||
|
||||
- UI API extension data-analysis 1.5.0 (requires QQQ 4.1.0-RC.15, UI API 1.6.0): operationIds, standard error responses with BasicErrorResponseV1, extension tags, contract validation for operationIds and schema references, and HTTP error envelope regression assertions.
|
||||
|
||||
- Pin QQQ 4.1.0-RC.7 and replace the temporary help loader with core bundle registration and startup sync.
|
||||
|
||||
- Boolean pivot/crosstab headers now say Yes / No / (Blank). Pivot measures use human labels such as Count, Average Amount, Sum of Amount, Distinct Email, Median Amount and 90th percentile of Amount.
|
||||
|
||||
@@ -135,6 +135,7 @@
|
||||
<filtering>true</filtering>
|
||||
<includes>
|
||||
<include>help/*.yaml</include>
|
||||
<include>qbit-data-analysis.properties</include>
|
||||
</includes>
|
||||
</resource>
|
||||
<resource>
|
||||
@@ -142,10 +143,20 @@
|
||||
<filtering>false</filtering>
|
||||
<excludes>
|
||||
<exclude>help/*.yaml</exclude>
|
||||
<exclude>qbit-data-analysis.properties</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemPropertyVariables combine.children="append">
|
||||
<qbit.artifactVersion>${project.version}</qbit.artifactVersion>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
@@ -232,7 +243,7 @@
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<qqq.snapshot.version>4.1.0-RC.7</qqq.snapshot.version>
|
||||
<qqq.snapshot.version>4.1.0-RC.15</qqq.snapshot.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
package com.kingsrook.qbits.dataanalysis;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
import com.kingsrook.qbits.dataanalysis.api.DataAnalysisApi;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerMultiOutput;
|
||||
@@ -40,13 +43,41 @@ public class DataAnalysisQBitProducer implements QBitMetaDataProducer<DataAnalys
|
||||
{
|
||||
public static final String GROUP_ID = "com.kingsrook.qbits";
|
||||
public static final String ARTIFACT_ID = "qbit-data-analysis";
|
||||
public static final String VERSION = "0.1.0";
|
||||
public static final String VERSION = loadVersion();
|
||||
|
||||
private DataAnalysisQBitConfig qBitConfig;
|
||||
private String namespace;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Read the artifact version from the Maven-filtered properties resource.
|
||||
*******************************************************************************/
|
||||
private static String loadVersion()
|
||||
{
|
||||
try(InputStream inputStream = DataAnalysisQBitProducer.class.getClassLoader().getResourceAsStream("qbit-data-analysis.properties"))
|
||||
{
|
||||
if(inputStream == null)
|
||||
{
|
||||
throw (new IllegalStateException("Missing qbit-data-analysis.properties; build with Maven to generate the artifact version"));
|
||||
}
|
||||
Properties properties = new Properties();
|
||||
properties.load(inputStream);
|
||||
String version = properties.getProperty("version");
|
||||
if(version == null || version.isBlank() || version.contains("${"))
|
||||
{
|
||||
throw (new IllegalStateException("Missing or unfiltered version in qbit-data-analysis.properties; build with Maven resource filtering"));
|
||||
}
|
||||
return (version);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw (new IllegalStateException("Could not read artifact version from qbit-data-analysis.properties", e));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent configuration setter.
|
||||
*******************************************************************************/
|
||||
|
||||
@@ -76,7 +76,7 @@ public class DataAnalysisApi
|
||||
*******************************************************************************/
|
||||
public static MiddlewareSpecExtension extension()
|
||||
{
|
||||
return (new MiddlewareSpecExtension().withName("data-analysis").withSemanticVersion("1.4.0")
|
||||
return (new MiddlewareSpecExtension().withName("data-analysis").withSemanticVersion("1.5.0")
|
||||
.withDescription("Profiles, pivots, comparisons, distribution shifts, correlations, scatter samples, crosstabs and anomaly watch previews as the signed-in user.")
|
||||
.withSpec(SavedApi.Run.class).withSpec(SavedApi.ListSaved.class).withSpec(SavedApi.Star.class).withSpec(SavedApi.Unstar.class)
|
||||
.withSpec(SavedApi.Sql.class).withSpec(AnalysisFileSpec.class).withSpec(AnalysisFileSpec.Saved.class)
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1 @@
|
||||
version=${project.version}
|
||||
@@ -136,6 +136,13 @@ class DataAnalysisApiTest extends EngineFixture
|
||||
}
|
||||
var response = invoker.invoke(request);
|
||||
assertThat(response.getStatus()).as(response.getBody()).isEqualTo(status);
|
||||
if(status >= 400)
|
||||
{
|
||||
for(String field : List.of("error", "code", "message", "traceId"))
|
||||
{
|
||||
assertThat(response.getJson().path(field).asText()).as(field).isNotBlank();
|
||||
}
|
||||
}
|
||||
return (response.getJson());
|
||||
}
|
||||
|
||||
@@ -282,7 +289,7 @@ class DataAnalysisApiTest extends EngineFixture
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
** Generated fragment is committed verbatim and has all fourteen operations.
|
||||
** Generated fragment matches the committed contract and validates all references.
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void contract() throws Exception
|
||||
@@ -296,8 +303,9 @@ class DataAnalysisApiTest extends EngineFixture
|
||||
Files.createDirectories(path.getParent());
|
||||
Files.writeString(path, yaml);
|
||||
}
|
||||
assertThat(Files.exists(path)).as("Regenerate with ./mvnw -o test -Dtest=DataAnalysisApiTest#contract -Dopenapi.write=true -Dqqq.snapshot.version=4.1.0-DATAANALYSIS-SNAPSHOT").isTrue();
|
||||
assertThat(Files.exists(path)).as("Regenerate with ./mvnw -o test -Dtest=DataAnalysisApiTest#contract -Dopenapi.write=true -Dqqq.snapshot.version=4.1.99-SNAPSHOT").isTrue();
|
||||
assertThat(Files.readString(path).replace("\r\n", "\n")).as("OpenAPI changed: regenerate with -Dopenapi.write=true").isEqualTo(yaml.replace("\r\n", "\n"));
|
||||
assertThat(UiApiContract.check(yaml, Files.readString(path), null, 1, "-Dopenapi.write=true")).isEmpty();
|
||||
}
|
||||
@Test
|
||||
void pivotHttp() throws Exception
|
||||
@@ -364,7 +372,7 @@ class DataAnalysisApiTest extends EngineFixture
|
||||
}
|
||||
relationshipCountDrills(call(HttpMethod.POST, "/tables/{table}/crosstab", Map.of("rowField", "status", "columnField", "customer"), 200));
|
||||
// All new schemas are discoverable from the same served OpenAPI catalog.
|
||||
assertThat(com.kingsrook.qbits.dataanalysis.api.DataAnalysisApi.extension().getSemanticVersion()).isEqualTo("1.4.0");
|
||||
assertThat(com.kingsrook.qbits.dataanalysis.api.DataAnalysisApi.extension().getSemanticVersion()).isEqualTo("1.5.0");
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
@@ -116,11 +116,15 @@ class DataAnalysisMetadataTest
|
||||
assertThat(producer.isEnabled()).isTrue();
|
||||
assertThat(producer.getNamespace()).isEqualTo("analysis");
|
||||
assertThat(producer.getQBitConfig()).isSameAs(config);
|
||||
assertThat(producer.getQBitMetaData().getVersion()).isEqualTo("0.1.0");
|
||||
String artifactVersion = System.getProperty("qbit.artifactVersion");
|
||||
assertThat(artifactVersion).isNotBlank();
|
||||
assertThat(producer.getQBitMetaData().getVersion()).isEqualTo(artifactVersion).isEqualTo(DataAnalysisQBitProducer.VERSION);
|
||||
assertThat(producer.getQBitMetaData().getGroupId()).isEqualTo("com.kingsrook.qbits");
|
||||
assertThat(producer.getQBitMetaData().getArtifactId()).isEqualTo("qbit-data-analysis");
|
||||
assertThat(producer.getPackageNameForFindingMetaDataProducers()).endsWith(".metadata");
|
||||
producer.produce(instance);
|
||||
assertThat(HelpBundles.of(instance).getBundles().getFirst().getVersion())
|
||||
.isEqualTo(artifactVersion).isEqualTo(producer.getQBitMetaData().getVersion());
|
||||
assertThat(HelpBundles.of(instance).getBundles().getFirst().getEntries()).anyMatch(entry -> entry.getKey().equals("app:customAnalysis;slot:help"))
|
||||
.noneMatch(entry -> entry.getKey().equals("app:dataAnalysis;slot:help"));
|
||||
assertThat(instance.getApp("customAnalysis").getParentAppName()).isEqualTo("admin");
|
||||
|
||||
Reference in new issue
Block a user