From ab09996ddedd7f46114314a21b1884c30355494d Mon Sep 17 00:00:00 2001 From: Sascha Fendrich Date: Mon, 27 Jan 2025 10:47:20 +0100 Subject: [PATCH 1/6] refactor: replace usage of field by getter This is a preparatory step for moving ithe methods `setSpeedups` and `requiresTimeDependentAlgorithm` from RoutingProfile to RoutingRequest. --- .../java/org/heigit/ors/routing/RoutingProfile.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java index 3000c041a5..acac5a11d9 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java @@ -199,9 +199,11 @@ public void setSpeedups(GHRequest req, boolean useCH, boolean useCore, boolean u //Priority: CH->Core->ALT String profileNameNoTC = requestProfileName.replace("_with_turn_costs", ""); - useCH = useCH && mGraphHopper.isCHAvailable(profileNameCH); - useCore = useCore && !useCH && (mGraphHopper.isCoreAvailable(requestProfileName) || mGraphHopper.isCoreAvailable(profileNameNoTC)); - useALT = useALT && !useCH && !useCore && mGraphHopper.isLMAvailable(requestProfileName); + ORSGraphHopper gh = getGraphhopper(); + + useCH = useCH && gh.isCHAvailable(profileNameCH); + useCore = useCore && !useCH && (gh.isCoreAvailable(requestProfileName) || gh.isCoreAvailable(profileNameNoTC)); + useALT = useALT && !useCH && !useCore && gh.isLMAvailable(requestProfileName); req.getHints().putObject(ProfileTools.KEY_CH_DISABLE, !useCH); req.getHints().putObject(ProfileTools.KEY_CORE_DISABLE, !useCore); @@ -211,7 +213,7 @@ public void setSpeedups(GHRequest req, boolean useCH, boolean useCore, boolean u req.setAlgorithm(Parameters.Algorithms.DIJKSTRA_BI); req.setProfile(profileNameCH); } - if (useCore && !mGraphHopper.isCoreAvailable(requestProfileName) && mGraphHopper.isCoreAvailable(profileNameNoTC)) + if (useCore && !gh.isCoreAvailable(requestProfileName) && gh.isCoreAvailable(profileNameNoTC)) // fallback to a core profile without turn costs if one is available req.setProfile(profileNameNoTC); @@ -230,7 +232,7 @@ boolean requiresTimeDependentAlgorithm(RouteSearchParameters searchParams, Route return false; return flagEncoder.hasEncodedValue(EncodingManager.getKey(flagEncoder, ConditionalEdges.SPEED)) - || mGraphHopper.isTrafficEnabled(); + || getGraphhopper().isTrafficEnabled(); } public boolean equals(Object o) { From 84edcb87d5f77bb8dcfafe54db9e41a686b71133 Mon Sep 17 00:00:00 2001 From: Sascha Fendrich Date: Mon, 27 Jan 2025 10:59:38 +0100 Subject: [PATCH 2/6] refactor: prepare method movement Replace the direct access to SearchParameters by an indirect access through RoutingRequest, where the method will be moved to. --- .../src/main/java/org/heigit/ors/routing/RoutingProfile.java | 4 +++- .../src/main/java/org/heigit/ors/routing/RoutingRequest.java | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java index acac5a11d9..a8ec03cb82 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java @@ -219,7 +219,9 @@ public void setSpeedups(GHRequest req, boolean useCH, boolean useCore, boolean u } - boolean requiresTimeDependentAlgorithm(RouteSearchParameters searchParams, RouteSearchContext searchCntx) { + boolean requiresTimeDependentAlgorithm(RouteSearchContext searchCntx, RoutingRequest req) { + RouteSearchParameters searchParams = req.getSearchParameters(); + if (!searchParams.isTimeDependent()) return false; diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java index 78c36ac2ed..acf8a95c6e 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java @@ -468,7 +468,7 @@ else if (bearings[1] == null) if (TemporaryUtilShelter.supportWeightingMethod(profileType)) { ProfileTools.setWeightingMethod(req.getHints(), weightingMethod, profileType, TemporaryUtilShelter.hasTimeDependentSpeed(searchParams, searchCntx)); - if (routingProfile.requiresTimeDependentAlgorithm(searchParams, searchCntx)) + if (routingProfile.requiresTimeDependentAlgorithm(searchCntx, this)) flexibleMode = ProfileTools.KEY_FLEX_PREPROCESSED; flexibleMode = TemporaryUtilShelter.getFlexibilityMode(flexibleMode, searchParams, profileType); } else @@ -501,7 +501,7 @@ else if (bearings[1] == null) Instant time = dateTime.atZone(ZoneId.of("Europe/Berlin")).toInstant(); req.getHints().putObject(key, time); - if (routingProfile.requiresTimeDependentAlgorithm(searchParams, searchCntx)) { + if (routingProfile.requiresTimeDependentAlgorithm(searchCntx, this)) { req.getHints().putObject("time", time.toEpochMilli()); req.setAlgorithm(Parameters.Algorithms.TD_ASTAR); } From a0354fd158a519a58100de88d042f9bddba7be59 Mon Sep 17 00:00:00 2001 From: Sascha Fendrich Date: Mon, 27 Jan 2025 11:12:54 +0100 Subject: [PATCH 3/6] refactor: move method and simplify method signature --- .../heigit/ors/routing/RoutingProfile.java | 21 ---------------- .../heigit/ors/routing/RoutingRequest.java | 25 +++++++++++++++++-- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java index a8ec03cb82..99af63f208 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java @@ -15,9 +15,6 @@ import com.graphhopper.GHRequest; import com.graphhopper.config.CHProfile; -import com.graphhopper.routing.util.EncodingManager; -import com.graphhopper.routing.util.FlagEncoder; -import com.graphhopper.storage.ConditionalEdges; import com.graphhopper.storage.GraphHopperStorage; import com.graphhopper.storage.StorableProperties; import com.graphhopper.util.Parameters; @@ -219,24 +216,6 @@ public void setSpeedups(GHRequest req, boolean useCH, boolean useCore, boolean u } - boolean requiresTimeDependentAlgorithm(RouteSearchContext searchCntx, RoutingRequest req) { - RouteSearchParameters searchParams = req.getSearchParameters(); - - if (!searchParams.isTimeDependent()) - return false; - - FlagEncoder flagEncoder = searchCntx.getEncoder(); - - if (flagEncoder.hasEncodedValue(EncodingManager.getKey(flagEncoder, ConditionalEdges.ACCESS))) - return true; - - if (WeightingMethod.SHORTEST == searchParams.getWeightingMethod()) - return false; - - return flagEncoder.hasEncodedValue(EncodingManager.getKey(flagEncoder, ConditionalEdges.SPEED)) - || getGraphhopper().isTrafficEnabled(); - } - public boolean equals(Object o) { return o != null && o.getClass().equals(RoutingProfile.class) && this.hashCode() == o.hashCode(); } diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java index acf8a95c6e..b0e804b022 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java @@ -16,6 +16,9 @@ import com.graphhopper.GHRequest; import com.graphhopper.GHResponse; import com.graphhopper.gtfs.*; +import com.graphhopper.routing.util.EncodingManager; +import com.graphhopper.routing.util.FlagEncoder; +import com.graphhopper.storage.ConditionalEdges; import com.graphhopper.util.*; import com.graphhopper.util.exceptions.MaximumNodesExceededException; import com.graphhopper.util.shapes.GHPoint; @@ -468,7 +471,7 @@ else if (bearings[1] == null) if (TemporaryUtilShelter.supportWeightingMethod(profileType)) { ProfileTools.setWeightingMethod(req.getHints(), weightingMethod, profileType, TemporaryUtilShelter.hasTimeDependentSpeed(searchParams, searchCntx)); - if (routingProfile.requiresTimeDependentAlgorithm(searchCntx, this)) + if (requiresTimeDependentAlgorithm(searchCntx)) flexibleMode = ProfileTools.KEY_FLEX_PREPROCESSED; flexibleMode = TemporaryUtilShelter.getFlexibilityMode(flexibleMode, searchParams, profileType); } else @@ -501,7 +504,7 @@ else if (bearings[1] == null) Instant time = dateTime.atZone(ZoneId.of("Europe/Berlin")).toInstant(); req.getHints().putObject(key, time); - if (routingProfile.requiresTimeDependentAlgorithm(searchCntx, this)) { + if (requiresTimeDependentAlgorithm(searchCntx)) { req.getHints().putObject("time", time.toEpochMilli()); req.setAlgorithm(Parameters.Algorithms.TD_ASTAR); } @@ -882,4 +885,22 @@ private RouteResult[] computeLinearRoute() throws Exception { } return new RouteResultBuilder().createRouteResults(routes, this, extraInfos); } + + boolean requiresTimeDependentAlgorithm(RouteSearchContext searchCntx) { + RouteSearchParameters searchParams = getSearchParameters(); + + if (!searchParams.isTimeDependent()) + return false; + + FlagEncoder flagEncoder = searchCntx.getEncoder(); + + if (flagEncoder.hasEncodedValue(EncodingManager.getKey(flagEncoder, ConditionalEdges.ACCESS))) + return true; + + if (WeightingMethod.SHORTEST == searchParams.getWeightingMethod()) + return false; + + return flagEncoder.hasEncodedValue(EncodingManager.getKey(flagEncoder, ConditionalEdges.SPEED)) + || profile().getGraphhopper().isTrafficEnabled(); + } } From a4ee9618b990174c3c30f3a566189e41a903ba3b Mon Sep 17 00:00:00 2001 From: Sascha Fendrich Date: Mon, 27 Jan 2025 11:21:28 +0100 Subject: [PATCH 4/6] refactor: prepare method movement This commit adds a parameter of type RoutingRequest to setSpeedups in order to move this method from RoutingProfile to RoutingReqest. --- .../main/java/org/heigit/ors/routing/RoutingProfile.java | 5 +++-- .../main/java/org/heigit/ors/routing/RoutingRequest.java | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java index 99af63f208..1ee6b03c9e 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java @@ -185,18 +185,19 @@ public Double getAstarEpsilon() { * Set the speedup techniques used for calculating the route. * Reults in usage of CH, Core or ALT/AStar, if they are enabled. * + * @param routingRequest * @param req Request whose hints will be set * @param useCH Should CH be enabled * @param useCore Should Core be enabled * @param useALT Should ALT be enabled */ - public void setSpeedups(GHRequest req, boolean useCH, boolean useCore, boolean useALT, String profileNameCH) { + public void setSpeedups(GHRequest req, boolean useCH, boolean useCore, boolean useALT, String profileNameCH, RoutingRequest routingRequest) { String requestProfileName = req.getProfile(); //Priority: CH->Core->ALT String profileNameNoTC = requestProfileName.replace("_with_turn_costs", ""); - ORSGraphHopper gh = getGraphhopper(); + ORSGraphHopper gh = routingRequest.profile().getGraphhopper(); useCH = useCH && gh.isCHAvailable(profileNameCH); useCore = useCore && !useCH && (gh.isCoreAvailable(requestProfileName) || gh.isCoreAvailable(profileNameNoTC)); diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java index b0e804b022..250ba4891c 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java @@ -480,15 +480,15 @@ else if (bearings[1] == null) if (flexibleMode == ProfileTools.KEY_FLEX_STATIC) //Speedup order: useCH, useCore, useALT // TODO Future improvement: profileNameCH is an ugly hack and is required because of the hard-coded turnCost=false for CH - routingProfile.setSpeedups(req, true, true, true, searchCntx.profileNameCH()); + routingProfile.setSpeedups(req, true, true, true, searchCntx.profileNameCH(), this); if (flexibleMode == ProfileTools.KEY_FLEX_PREPROCESSED) { - routingProfile.setSpeedups(req, false, optimized, true, searchCntx.profileNameCH()); + routingProfile.setSpeedups(req, false, optimized, true, searchCntx.profileNameCH(), this); } //cannot use CH or CoreALT with requests where the weighting of non-predefined edges might change if (flexibleMode == ProfileTools.KEY_FLEX_FULLY) - routingProfile.setSpeedups(req, false, false, true, searchCntx.profileNameCH()); + routingProfile.setSpeedups(req, false, false, true, searchCntx.profileNameCH(), this); if (searchParams.isTimeDependent()) { String key; @@ -588,7 +588,7 @@ private GHResponse computeRoundTripRoute(double lat0, double lon0, WayPointBeari throw new IllegalArgumentException("Unsupported weighting " + weightingMethod + " for profile + " + profileType); //Roundtrip not possible with preprocessed edges. - routingProfile.setSpeedups(req, false, false, true, searchCntx.profileNameCH()); + routingProfile.setSpeedups(req, false, false, true, searchCntx.profileNameCH(), this); if (routingProfile.getAstarEpsilon() != null) req.getHints().putObject("astarbi.epsilon", routingProfile.getAstarEpsilon()); From 34a90ca701d74ba87d9ae15b11ec08214b2a1f37 Mon Sep 17 00:00:00 2001 From: Sascha Fendrich Date: Mon, 27 Jan 2025 11:27:45 +0100 Subject: [PATCH 5/6] refactor: move method --- .../heigit/ors/routing/RoutingProfile.java | 39 ---------------- .../heigit/ors/routing/RoutingRequest.java | 44 +++++++++++++++++-- 2 files changed, 40 insertions(+), 43 deletions(-) diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java index 1ee6b03c9e..799ec22f9a 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java @@ -13,11 +13,9 @@ */ package org.heigit.ors.routing; -import com.graphhopper.GHRequest; import com.graphhopper.config.CHProfile; import com.graphhopper.storage.GraphHopperStorage; import com.graphhopper.storage.StorableProperties; -import com.graphhopper.util.Parameters; import org.apache.log4j.Logger; import org.heigit.ors.config.EngineProperties; import org.heigit.ors.config.profile.ExecutionProperties; @@ -27,7 +25,6 @@ import org.heigit.ors.routing.graphhopper.extensions.storages.builders.BordersGraphStorageBuilder; import org.heigit.ors.routing.graphhopper.extensions.storages.builders.GraphStorageBuilder; import org.heigit.ors.routing.pathprocessors.ORSPathProcessorFactory; -import org.heigit.ors.util.ProfileTools; import org.heigit.ors.util.TimeUtility; import java.io.File; @@ -181,42 +178,6 @@ public Double getAstarEpsilon() { return astarEpsilon; } - /** - * Set the speedup techniques used for calculating the route. - * Reults in usage of CH, Core or ALT/AStar, if they are enabled. - * - * @param routingRequest - * @param req Request whose hints will be set - * @param useCH Should CH be enabled - * @param useCore Should Core be enabled - * @param useALT Should ALT be enabled - */ - public void setSpeedups(GHRequest req, boolean useCH, boolean useCore, boolean useALT, String profileNameCH, RoutingRequest routingRequest) { - String requestProfileName = req.getProfile(); - - //Priority: CH->Core->ALT - String profileNameNoTC = requestProfileName.replace("_with_turn_costs", ""); - - ORSGraphHopper gh = routingRequest.profile().getGraphhopper(); - - useCH = useCH && gh.isCHAvailable(profileNameCH); - useCore = useCore && !useCH && (gh.isCoreAvailable(requestProfileName) || gh.isCoreAvailable(profileNameNoTC)); - useALT = useALT && !useCH && !useCore && gh.isLMAvailable(requestProfileName); - - req.getHints().putObject(ProfileTools.KEY_CH_DISABLE, !useCH); - req.getHints().putObject(ProfileTools.KEY_CORE_DISABLE, !useCore); - req.getHints().putObject(ProfileTools.KEY_LM_DISABLE, !useALT); - - if (useCH) { - req.setAlgorithm(Parameters.Algorithms.DIJKSTRA_BI); - req.setProfile(profileNameCH); - } - if (useCore && !gh.isCoreAvailable(requestProfileName) && gh.isCoreAvailable(profileNameNoTC)) - // fallback to a core profile without turn costs if one is available - req.setProfile(profileNameNoTC); - - } - public boolean equals(Object o) { return o != null && o.getClass().equals(RoutingProfile.class) && this.hashCode() == o.hashCode(); } diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java index 250ba4891c..0bb9c148c5 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingRequest.java @@ -480,15 +480,15 @@ else if (bearings[1] == null) if (flexibleMode == ProfileTools.KEY_FLEX_STATIC) //Speedup order: useCH, useCore, useALT // TODO Future improvement: profileNameCH is an ugly hack and is required because of the hard-coded turnCost=false for CH - routingProfile.setSpeedups(req, true, true, true, searchCntx.profileNameCH(), this); + setSpeedups(req, true, true, true, searchCntx.profileNameCH()); if (flexibleMode == ProfileTools.KEY_FLEX_PREPROCESSED) { - routingProfile.setSpeedups(req, false, optimized, true, searchCntx.profileNameCH(), this); + setSpeedups(req, false, optimized, true, searchCntx.profileNameCH()); } //cannot use CH or CoreALT with requests where the weighting of non-predefined edges might change if (flexibleMode == ProfileTools.KEY_FLEX_FULLY) - routingProfile.setSpeedups(req, false, false, true, searchCntx.profileNameCH(), this); + setSpeedups(req, false, false, true, searchCntx.profileNameCH()); if (searchParams.isTimeDependent()) { String key; @@ -588,7 +588,7 @@ private GHResponse computeRoundTripRoute(double lat0, double lon0, WayPointBeari throw new IllegalArgumentException("Unsupported weighting " + weightingMethod + " for profile + " + profileType); //Roundtrip not possible with preprocessed edges. - routingProfile.setSpeedups(req, false, false, true, searchCntx.profileNameCH(), this); + setSpeedups(req, false, false, true, searchCntx.profileNameCH()); if (routingProfile.getAstarEpsilon() != null) req.getHints().putObject("astarbi.epsilon", routingProfile.getAstarEpsilon()); @@ -903,4 +903,40 @@ boolean requiresTimeDependentAlgorithm(RouteSearchContext searchCntx) { return flagEncoder.hasEncodedValue(EncodingManager.getKey(flagEncoder, ConditionalEdges.SPEED)) || profile().getGraphhopper().isTrafficEnabled(); } + + /** + * Set the speedup techniques used for calculating the route. + * Reults in usage of CH, Core or ALT/AStar, if they are enabled. + * + * @param req Request whose hints will be set + * @param useCH Should CH be enabled + * @param useCore Should Core be enabled + * @param useALT Should ALT be enabled + * @param profileNameCH + */ + public void setSpeedups(GHRequest req, boolean useCH, boolean useCore, boolean useALT, String profileNameCH) { + String requestProfileName = req.getProfile(); + + //Priority: CH->Core->ALT + String profileNameNoTC = requestProfileName.replace("_with_turn_costs", ""); + + ORSGraphHopper gh = profile().getGraphhopper(); + + useCH = useCH && gh.isCHAvailable(profileNameCH); + useCore = useCore && !useCH && (gh.isCoreAvailable(requestProfileName) || gh.isCoreAvailable(profileNameNoTC)); + useALT = useALT && !useCH && !useCore && gh.isLMAvailable(requestProfileName); + + req.getHints().putObject(ProfileTools.KEY_CH_DISABLE, !useCH); + req.getHints().putObject(ProfileTools.KEY_CORE_DISABLE, !useCore); + req.getHints().putObject(ProfileTools.KEY_LM_DISABLE, !useALT); + + if (useCH) { + req.setAlgorithm(Parameters.Algorithms.DIJKSTRA_BI); + req.setProfile(profileNameCH); + } + if (useCore && !gh.isCoreAvailable(requestProfileName) && gh.isCoreAvailable(profileNameNoTC)) + // fallback to a core profile without turn costs if one is available + req.setProfile(profileNameNoTC); + + } } From b697c17ec68b2369b27b8426b9cdeb62a50bd470 Mon Sep 17 00:00:00 2001 From: Sascha Fendrich Date: Mon, 27 Jan 2025 12:22:29 +0100 Subject: [PATCH 6/6] fix: tool versions in dockerfile Fixed tool versions in Builder.Dockerfile lead to failure building the integration test container. --- ors-test-scenarios/src/test/resources/Builder.Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ors-test-scenarios/src/test/resources/Builder.Dockerfile b/ors-test-scenarios/src/test/resources/Builder.Dockerfile index fb22566a45..3847b02e21 100644 --- a/ors-test-scenarios/src/test/resources/Builder.Dockerfile +++ b/ors-test-scenarios/src/test/resources/Builder.Dockerfile @@ -9,7 +9,7 @@ ARG CONTAINER_WORK_DIR=/home/ors/openrouteservice FROM docker.io/maven:3.9.9-amazoncorretto-21-alpine AS ors-test-scenarios-builder -RUN apk add --no-cache bash=5.2.26-r0 yq=4.44.1-r2 zip=3.0-r12 && \ +RUN apk add --no-cache bash~=5 yq~=4 zip~=3 && \ rm -rf /var/cache/apk/* ARG CONTAINER_BUILD_DIR @@ -101,7 +101,7 @@ ENV JAVA_OPTS="-Xmx350M" FROM docker.io/amazoncorretto:21.0.4-alpine3.20 AS ors-test-scenarios-jar-builder # Build: docker build --target ors-test-scenarios-jar-bare --tag ors-test-scenarios-jar-bare:latest -f ors-test-scenarios/src/test/resources/Dockerfile . -RUN apk add --no-cache bash=5.2.26-r0 yq=4.44.1-r2 zip=3.0-r12 +RUN apk add --no-cache bash~=5 yq~=4 zip~=3 ARG CONTAINER_WORK_DIR ARG CONTAINER_BUILD_DIR