Skip to content

Commit

Permalink
chore: upgrade PlantUML to 1.2025.0 (#1830)
Browse files Browse the repository at this point in the history
  • Loading branch information
ggrossetie authored Feb 22, 2025
1 parent d61308c commit 0bdd114
Show file tree
Hide file tree
Showing 21 changed files with 1,404 additions and 1,312 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.DS_store
target/
/.registry/oci/*
*.iml
Expand Down
2 changes: 1 addition & 1 deletion ci/tests/smoke.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ describe('CJK font', function () {
const response = await sendRequest(testCase, 'svg')
const textResponse = await response.text()
try {
deepEqual(textResponse.includes('textLength="56"'), true, `text response must include textLength="56" in: ${textResponse}`)
deepEqual(textResponse.includes('textLength="55.9'), true, `text response must include textLength="55.9 in: ${textResponse}`)
} catch (err) {
console.log('response:', textResponse)
throw err
Expand Down
4 changes: 2 additions & 2 deletions docs/antora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ asciidoc:
blockdiag-version: 3.1.0
bpmn-version: 18.0.0
bytefield-version: 1.10.0
c4plantuml-version: 1.2024.1
c4plantuml-version: 1.2025.0
d2-version: 0.6.3
dbml-version: 1.0.30
diagramsnet-version: 16.2.4
Expand All @@ -20,7 +20,7 @@ asciidoc:
nwdiag-version: 3.1.0
packetdiag-version: 3.1.0
pikchr-version: '7269f78c4a'
plantuml-version: 1.2024.1
plantuml-version: 1.2025.0
rackdiag-version: 3.1.0
seqdiag-version: 3.1.0
structurizr-version: 3.0.0
Expand Down
8 changes: 6 additions & 2 deletions server/ops/docker/jdk17-noble/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ ARG D2_VERSION="0.6.3"
ARG DITAA_VERSION="1.0.3"
ARG DVISVGM_VERSION="3.2.1+ds-1build1"
ARG GRAPHVIZ_VERSION="9.0.0"
ARG PLANTUML_VERSION="1.2024.1"
ARG PLANTUML_VERSION="1.2025.0"
ARG UMLET_VERSION="2023-03-20_UMLet_v15.1"
ARG WIREVIZ_VERSION="0.3.3"
ARG TARGETARCH
Expand All @@ -202,6 +202,7 @@ RUN apt-get update && apt-get install --no-install-recommends --yes \
# * texlive-pictures - Provides various graphics packages like "circuitikz"
# * texlive-science - Provides various science packages like "siunitx"
RUN apt-get update && apt-get install --no-install-recommends --yes \
unzip \
dvisvgm=$DVISVGM_VERSION \
libpango1.0-dev \
librsvg2-dev \
Expand Down Expand Up @@ -239,7 +240,10 @@ RUN wget "https://github.com/terrastruct/d2/releases/download/v${D2_VERSION}/d2-
mv usr/bin/d2-v${D2_VERSION}/bin/d2 /usr/bin/d2 && \
chmod +x /usr/bin/d2

RUN wget "https://github.com/yuzutech/plantuml/releases/download/v${PLANTUML_VERSION}/plantuml-linux-${TARGETARCH}-${PLANTUML_VERSION}" -O /usr/bin/plantuml && \
RUN wget "https://github.com/yuzutech/plantuml/releases/download/v${PLANTUML_VERSION}/plantuml-linux-${TARGETARCH}-${PLANTUML_VERSION}.zip" -O plantuml-bin.zip && \
unzip plantuml-bin.zip -d plantuml && \
mv plantuml/* /usr/bin/ && \
mv /usr/bin/plantuml-linux-${TARGETARCH}-${PLANTUML_VERSION} /usr/bin/plantuml && \
chmod +x /usr/bin/plantuml

RUN wget "https://github.com/yuzutech/umlet/releases/download/${UMLET_VERSION}/umlet-linux-${TARGETARCH}" -O /usr/bin/umlet && \
Expand Down
2 changes: 1 addition & 1 deletion server/src/main/java/io/kroki/server/service/Plantuml.java
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public SourceDecoder getSourceDecoder() {

@Override
public String getVersion() {
return "1.2024.1";
return "1.2025.0";
}

@Override
Expand Down
2,512 changes: 1,256 additions & 1,256 deletions server/src/main/resources/structurizr/amazon-web-services-2020.04.30.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"tag" : "Amazon Web Services - Route 53 Application Recovery Controller",
"stroke" : "#4d27aa",
"color" : "#4d27aa",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2022.04.30/Res_Amazon-Route-53_Application-Recovery-Controller_48_Light.png"
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2022.04.30/https://static.structurizr.com/themes/amazon-web-services-2022.04.30//Res_Amazon-Route-53_Application-Recovery-Controller_48_Light.png"
}, {
"tag" : "Amazon Web Services - DynamoDB Standard Infrequent Access Table Class",
"stroke" : "#2e27ad",
Expand Down Expand Up @@ -142,7 +142,7 @@
"color" : "#de2d34",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2022.04.30/Arch_Amazon-Connect_48.png"
}, {
"tag" : "Amazon Web Services - AWS IoT Sailboat ",
"tag" : "Amazon Web Services - AWS IoT Sailboat",
"stroke" : "#3f8624",
"color" : "#3f8624",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2022.04.30/Res_AWS-IoT_Sailboat _48_Light.png"
Expand Down Expand Up @@ -877,7 +877,7 @@
"color" : "#d45b07",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2022.04.30/Res_Amazon-EC2_M5dn-Instance_48_Light.png"
}, {
"tag" : "Amazon Web Services - EC2 R5b Instance ",
"tag" : "Amazon Web Services - EC2 R5b Instance",
"stroke" : "#d45b07",
"color" : "#d45b07",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2022.04.30/Res_Amazon-EC2_R5b-Instance _48_Light.png"
Expand Down Expand Up @@ -2122,7 +2122,7 @@
"color" : "#7545d1",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2022.04.30/Arch_AWS-App-Mesh_48.png"
}, {
"tag" : "Amazon Web Services - AWS IoT LoRaWAN Protocol ",
"tag" : "Amazon Web Services - AWS IoT LoRaWAN Protocol",
"stroke" : "#3f8624",
"color" : "#3f8624",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2022.04.30/Res_AWS-IoT_LoRaWAN-Protocol _48_Light.png"
Expand Down Expand Up @@ -2337,7 +2337,7 @@
"color" : "#4d27aa",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2022.04.30/Res_Amazon-VPC_Traffic-Mirroring_48_Light.png"
}, {
"tag" : "Amazon Web Services - EC2 AWS Microservice Extractor for ",
"tag" : "Amazon Web Services - EC2 AWS Microservice Extractor for",
"stroke" : "#d45b07",
"color" : "#d45b07",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2022.04.30/Res_Amazon-EC2_AWS-Microservice-Extractor-for-.NET_48_Light.png"
Expand Down Expand Up @@ -3142,7 +3142,7 @@
"color" : "#4d27aa",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2022.04.30/Res_Amazon-VPC_VPN-Gateway_48_Light.png"
}, {
"tag" : "Amazon Web Services - Console Mobile Application ",
"tag" : "Amazon Web Services - Console Mobile Application",
"stroke" : "#da2e6e",
"color" : "#da2e6e",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2022.04.30/Arch_AWS-Console-Mobile-Application _48.png"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@
"stroke" : "#b0084d",
"color" : "#b0084d",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Res_AWS-License-Manager_Application-Discovery_48_Light.png"
}, {
"tag" : "Amazon Web Services - API Gateway",
"stroke" : "#d72b6c",
"color" : "#d72b6c",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Arch_Amazon-API-Gateway_48.png"
}, {
"tag" : "Amazon Web Services - AWS IoT Greengrass Component",
"stroke" : "#3f8624",
Expand Down Expand Up @@ -171,11 +176,6 @@
"stroke" : "#de2d34",
"color" : "#de2d34",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Arch_Amazon-Connect_48.png"
}, {
"tag" : "Amazon Web Services - AWS IoT Sailboat",
"stroke" : "#3f8624",
"color" : "#3f8624",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Res_AWS-IoT_Sailboat _48_Light.png"
}, {
"tag" : "Amazon Web Services - Firewall Manager",
"stroke" : "#de2d34",
Expand Down Expand Up @@ -466,11 +466,6 @@
"stroke" : "#3f8624",
"color" : "#3f8624",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Res_AWS-IoT-Greengrass_Component-Public_48_Light.png"
}, {
"tag" : "Amazon Web Services - Amazon API Gateway",
"stroke" : "#d72b6c",
"color" : "#d72b6c",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Arch_ Amazon-API-Gateway_48.png"
}, {
"tag" : "Amazon Web Services - AWS Identity Access Management Data Encryption Key",
"stroke" : "#bf0816",
Expand Down Expand Up @@ -1016,11 +1011,6 @@
"stroke" : "#d45b07",
"color" : "#d45b07",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Res_Amazon-EC2_M5dn-Instance_48_Light.png"
}, {
"tag" : "Amazon Web Services - EC2 R5b Instance",
"stroke" : "#d45b07",
"color" : "#d45b07",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Res_Amazon-EC2_R5b-Instance _48_Light.png"
}, {
"tag" : "Amazon Web Services - EC2 C6g Instance",
"stroke" : "#d45b07",
Expand Down Expand Up @@ -1136,6 +1126,11 @@
"stroke" : "#e5770d",
"color" : "#e5770d",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Arch_Bottlerocket_48.png"
}, {
"tag" : "Amazon Web Services - AWS IoT Sailboat",
"stroke" : "#3f8624",
"color" : "#3f8624",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Res_AWS-IoT_Sailboat_48_Light.png"
}, {
"tag" : "Amazon Web Services - AWS IoT Actuator",
"stroke" : "#3f8624",
Expand Down Expand Up @@ -2096,6 +2091,11 @@
"stroke" : "#b0084d",
"color" : "#b0084d",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Res_AWS-CloudFormation_Change-Set_48_Light.png"
}, {
"tag" : "Amazon Web Services - AWS IoT LoRaWAN Protocol",
"stroke" : "#3f8624",
"color" : "#3f8624",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Res_AWS-IoT_LoRaWAN-Protocol_48_Light.png"
}, {
"tag" : "Amazon Web Services - Elemental Appliances & Software",
"stroke" : "#e5770d",
Expand Down Expand Up @@ -2411,11 +2411,6 @@
"stroke" : "#7545d1",
"color" : "#7545d1",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Arch_AWS-App-Mesh_48.png"
}, {
"tag" : "Amazon Web Services - AWS IoT LoRaWAN Protocol",
"stroke" : "#3f8624",
"color" : "#3f8624",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Res_AWS-IoT_LoRaWAN-Protocol _48_Light.png"
}, {
"tag" : "Amazon Web Services - EC2 Inf2 Instance",
"stroke" : "#d45b07",
Expand Down Expand Up @@ -3576,11 +3571,6 @@
"stroke" : "#4d27aa",
"color" : "#4d27aa",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Res_Amazon-VPC_VPN-Gateway_48_Light.png"
}, {
"tag" : "Amazon Web Services - Console Mobile Application",
"stroke" : "#da2e6e",
"color" : "#da2e6e",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Arch_AWS-Console-Mobile-Application _48.png"
}, {
"tag" : "Amazon Web Services - CloudWatch Event Event Based",
"stroke" : "#b0084d",
Expand Down Expand Up @@ -3816,6 +3806,16 @@
"stroke" : "#4053d6",
"color" : "#4053d6",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Arch_AWS-CodeStar_48.png"
}, {
"tag" : "Amazon Web Services - EC2 R5b Instance",
"stroke" : "#d45b07",
"color" : "#d45b07",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Res_Amazon-EC2_R5b-Instance_48_Light.png"
}, {
"tag" : "Amazon Web Services - Console Mobile Application",
"stroke" : "#da2e6e",
"color" : "#da2e6e",
"icon" : "https://static.structurizr.com/themes/amazon-web-services-2023.01.31/Arch_AWS-Console-Mobile-Application_48.png"
}, {
"tag" : "Amazon Web Services - Tools and SDKs",
"stroke" : "#4053d6",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class DownloadDitaaNativeImage {
public static Future<DitaaCommand> download(Vertx vertx) {
String ditaaVersion = new Ditaa(vertx, new JsonObject()).getVersion();
String downloadUrl = "https://github.com/yuzutech/ditaa-mini/releases/download/" + ditaaVersion + "/ditaamini-linux-amd64-" + ditaaVersion;
return DownloadNativeImage.download(vertx, downloadUrl, "Ditaa", "ditaamini-linux-amd64-" + ditaaVersion).map(ditaaBinPath -> {
return DownloadNativeImage.download(vertx, downloadUrl, "Ditaa", "ditaamini-linux-amd64-" + ditaaVersion, "ditaamini-linux-amd64-" + ditaaVersion).map(ditaaBinPath -> {
JsonObject options = new JsonObject();
options.put("KROKI_DITAA_BIN_PATH", ditaaBinPath);
return new DitaaCommand(options);
Expand Down
60 changes: 54 additions & 6 deletions server/src/test/java/io/kroki/server/DownloadNativeImage.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
import io.vertx.ext.web.client.HttpResponse;
import io.vertx.ext.web.client.WebClient;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class DownloadNativeImage {

public static Future<String> download(Vertx vertx, String downloadUrl, String commandName, String nativeImageName) {
public static Future<String> download(Vertx vertx, String downloadUrl, String commandName, String downloadFileName, String nativeImageName) {
String binPathOptionName = "KROKI_" + commandName.toUpperCase() + "_BIN_PATH";
String binPath = System.getenv(binPathOptionName);
if (binPath != null && !binPath.isBlank()) {
Expand Down Expand Up @@ -56,12 +56,16 @@ public static Future<String> download(Vertx vertx, String downloadUrl, String co
return Future.failedFuture(new IllegalAccessError("Request failed with status code " + statusCode + " and message " + bufferHttpResponse.statusMessage()));
}
try {
File nativeFile = nativePath.toFile();
try (FileOutputStream fos = new FileOutputStream(nativeFile)) {
Path downloadFilePath = Paths.get(buildDirectory, downloadFileName);
try (FileOutputStream fos = new FileOutputStream(downloadFilePath.toFile())) {
fos.write(bufferHttpResponse.body().getBytes());
} catch (IOException e) {
return Future.failedFuture(e);
}
if (downloadFileName.endsWith(".zip")) {
unzipFile(downloadFilePath, Paths.get(buildDirectory));
}
File nativeFile = nativePath.toFile();
boolean result = nativeFile.setExecutable(true);
if (!result) {
return Future.failedFuture(new IllegalAccessError("Unable to make " + nativeFile + " executable!"));
Expand All @@ -73,4 +77,48 @@ public static Future<String> download(Vertx vertx, String downloadUrl, String co
}
});
}

private static void unzipFile(Path zipFile, Path targetDirectory) throws IOException {
byte[] buffer = new byte[1024];
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile.toFile()));
ZipEntry zipEntry = zis.getNextEntry();
while (zipEntry != null) {
File newFile = newFile(targetDirectory.toFile(), zipEntry);
if (zipEntry.isDirectory()) {
if (!newFile.isDirectory() && !newFile.mkdirs()) {
throw new IOException("Failed to create directory " + newFile);
}
} else {
// fix for Windows-created archives
File parent = newFile.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
throw new IOException("Failed to create directory " + parent);
}

// write file content
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
}
zipEntry = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
}

private static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
File destFile = new File(destinationDir, zipEntry.getName());

String destDirPath = destinationDir.getCanonicalPath();
String destFilePath = destFile.getCanonicalPath();

if (!destFilePath.startsWith(destDirPath + File.separator)) {
throw new IOException("Entry is outside of the target dir: " + zipEntry.getName());
}

return destFile;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,50 @@ public class DownloadPlantumlNativeImage {

public static Future<PlantumlCommand> download(Vertx vertx) {
String plantumlVersion = new Plantuml(vertx, new JsonObject()).getVersion();
String downloadUrl = "https://github.com/yuzutech/plantuml/releases/download/v" + plantumlVersion + "/plantuml-linux-amd64-" + plantumlVersion;
return DownloadNativeImage.download(vertx, downloadUrl, "PlantUML", "plantuml-linux-amd64-" + plantumlVersion).map(plantumlBinPath -> {
String os = getOperatingSystemName();
String arch = getArch();
String zipName = "plantuml-" + os + "-" + arch + "-" + plantumlVersion + ".zip";
String binaryExtension = getBinaryExtension(os);
String binaryName = "plantuml-" + os + "-" + arch + "-" + plantumlVersion + binaryExtension;
String downloadUrl = "https://github.com/yuzutech/plantuml/releases/download/v1.2025.0/" + zipName;
return DownloadNativeImage.download(vertx, downloadUrl, "PlantUML", zipName, binaryName).map(plantumlBinPath -> {
JsonObject options = new JsonObject();
options.put("KROKI_PLANTUML_BIN_PATH", plantumlBinPath);
return new PlantumlCommand(options);
});
}

private static String getBinaryExtension(String os) {
String binaryExtension;
if (os.equals("win")) {
binaryExtension = ".exe";
} else {
binaryExtension = "";
}
return binaryExtension;
}

private static String getArch() {
String osArch = System.getProperty("os.arch");
String arch;
if (osArch.contains("aarch64")) {
arch = "arm64";
} else {
arch = "amd64";
}
return arch;
}

private static String getOperatingSystemName() {
String osName = System.getProperty("os.name");
String os;
if (osName.startsWith("Mac OS")) {
os = "darwin";
} else if (osName.startsWith("Windows")) {
os = "win";
} else {
os = "linux";
}
return os;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public void should_throw_exception_when_unknown_output_specified() throws IOExce
public void should_preserve_styles_defined_in_workspace_while_applying_theme() throws IOException, InterruptedException {
String source = read("./workspace-style-with-theme.structurizr");
byte[] convert = Structurizr.convert(source, FileFormat.SVG, plantumlCommand, new StructurizrPlantUMLExporter(), SafeMode.SAFE, new JsonObject());
assertThat(new String(convert)).isEqualTo(read("./workspace-style-with-theme.svg"));
assertThat(stripComments(new String(convert))).isEqualTo(read("./workspace-style-with-theme.svg"));
}

private String stripComments(String xmlContent) {
Expand Down
2 changes: 1 addition & 1 deletion server/src/test/resources/aws.expected.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion server/src/test/resources/bigbank.containers.expected.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 0bdd114

Please sign in to comment.