diff --git a/auto-devops/maven.gitlab-ci.yml b/auto-devops/maven.gitlab-ci.yml
index d3d77d509e111673f68e426096a7a8feb99161f4..9f14a7f8a7c4106ee5eb013ce77d279b34358555 100644
--- a/auto-devops/maven.gitlab-ci.yml
+++ b/auto-devops/maven.gitlab-ci.yml
@@ -21,6 +21,12 @@ variables:
   MAVEN_VERSION: "3.9-eclipse-temurin-8"
   MAVEN_IMAGE: maven:$MAVEN_VERSION
 
+# DinD service for Testcontainers support
+services:
+  - name: docker:dind
+    # explicitly disable tls to avoid docker startup interruption
+    command: ["--tls=false"]
+
 # Retrieve Access Token used to retrieve published Maven packages from GitLab Maven Repository
 .maven.deploy_tokens:
   - |
@@ -135,21 +141,39 @@ maven:verify:
 # Template deploy job for pipelines which *are* on the default branch.
 .maven:deploy:
   extends: .maven
-  stage: production
   script:
     - if [ ! -f ci_settings.xml ]; then
         echo "CI settings missing\! If deploying to GitLab Maven Repository, please see https://docs.gitlab.com/ee/user/packages/maven_repository/index.html#create-maven-packages-with-gitlab-cicd for instructions.";
       fi
     - mvn $MAVEN_CLI_OPTS clean deploy
   rules:
-    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
+    - if: $MAVEN_DEPLOY_DISABLED
       when: never
     - !reference [.maven, rules]
 
-# Deploy uses the default maven version.
+# Production Deploy uses the default maven version.
 maven:deploy:
   extends: .maven:deploy
+    stage: production
   rules:
-    - if: $MAVEN_DEPLOY_DISABLED
+    - if: $DISABLE_ARTIFACT_REGISTRY_PUSH
+      when: never
+    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
+      when: never
+    - !reference [".maven:deploy", rules]
+
+# Non-default branch deploy job - must be run manually as part of the review stage
+maven:deploy-dev:
+  extends: .maven:deploy
+  stage: review
+  rules:
+    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+      when: never
+    - if: $CI_COMMIT_TAG
       when: never
+    - if: $CI_COMMIT_BRANCH
+      when: manual
     - !reference [".maven:deploy", rules]
+      # This is currently the only way to allow the pipeline to succeed if the optional manual push job was
+      # not triggered. See the following issue for context - https://gitlab.com/gitlab-org/gitlab/-/issues/249524.
+      allow_failure: true