diff --git a/task/maven/0.4/README.md b/task/maven/0.4/README.md
new file mode 100644
index 0000000000..90af923c62
--- /dev/null
+++ b/task/maven/0.4/README.md
@@ -0,0 +1,288 @@
+# Maven
+
+This Task can be used to run a Maven goals on a simple maven project or on a multi-module maven project.
+
+## Install the Task
+
+```bash
+kubectl apply -f https://api.hub.tekton.dev/v1/resource/tekton/task/maven/0.3/raw
+```
+
+## Parameters
+
+- **MAVEN_IMAGE**: The base image for maven (_default_: `gcr.io/cloud-builders/mvn`)
+- **MAVEN_COMMAND**: Maven command to execute, you could use the maven wrapper over here (_default_: `/usr/bin/mvn`)
+- **GOALS**: Maven `goals` to be executed
+- **MAVEN_MIRROR_URL**: Maven mirror url (to be inserted into ~/.m2/settings.xml)
+- **SERVER_USER**: Username to authenticate to the server (to be inserted into ~/.m2/settings.xml)
+- **SERVER_PASSWORD**: Password to authenticate to the server (to be inserted into ~/.m2/settings.xml)
+- **PROXY_USER**: Username to login to the proxy server (to be inserted into ~/.m2/settings.xml)
+- **PROXY_PASSWORD**: Password to login to the proxy server (to be inserted into ~/.m2/settings.xml)
+- **PROXY_HOST**: Hostname of the proxy server (to be inserted into ~/.m2/settings.xml)
+- **PROXY_NON_PROXY_HOSTS**: Non proxy hosts to be reached directly bypassing the proxy (to be inserted into ~/.m2/settings.xml)
+- **PROXY_PORT**: Port number on which the proxy port listens (to be inserted into ~/.m2/settings.xml)
+- **PROXY_PROTOCOL**: http or https protocol whichever is applicable (to be inserted into ~/.m2/settings.xml)
+- **CONTEXT_DIR**: The context directory within the repository for sources on which we want to execute maven goals. (_Default_: ".")
+
+## Workspaces
+
+- **source**: `PersistentVolumeClaim`-type so that volume can be shared among `git-clone` and `maven` task
+
+```yaml
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: maven-source-pvc
+spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 500Mi
+```
+
+- **maven-local-repo**: `PersistentVolumeClaim`-type so that local m2 cache can be used in order to decrease maven-like tasks running time. If you are using `affinity-assistant` you won't be allowed to bind two PVC at the same time for a particular task. If that's your case you'll need disable it.
+```yaml
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: maven-local-m2-pvc
+spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 3Gi
+```
+
+## Platforms
+
+The Task can be run on `linux/amd64`, `linux/s390x` and `linux/ppc64le` platforms.
+
+For `linux/s390x` and `linux/ppc64le` platforms specify **MAVEN_IMAGE** parameter with `maven:3.6.3-adoptopenjdk-11` value in TaskRun or PipelineRun.
+
+## Usage
+
+This Pipeline and PipelineRun runs a Maven build on a particular module in a multi-module maven project
+
+### With Defaults
+
+```yaml
+apiVersion: tekton.dev/v1beta1
+kind: Pipeline
+metadata:
+ name: maven-test-pipeline
+spec:
+ workspaces:
+ - name: shared-workspace
+ - name: maven-settings
+ - name: maven-local-m2
+ tasks:
+ - name: fetch-repository
+ taskRef:
+ name: git-clone
+ workspaces:
+ - name: output
+ workspace: shared-workspace
+ params:
+ - name: url
+ value: https://github.com/redhat-developer-demos/tekton-tutorial
+ - name: subdirectory
+ value: ""
+ - name: deleteExisting
+ value: "true"
+ - name: maven-run
+ taskRef:
+ name: maven
+ runAfter:
+ - fetch-repository
+ params:
+ - name: CONTEXT_DIR
+ value: "apps/greeter/java/quarkus"
+ - name: GOALS
+ value:
+ - -DskipTests
+ - clean
+ - package
+ workspaces:
+ - name: maven-settings
+ workspace: maven-settings
+ - name: source
+ workspace: shared-workspace
+ - name: maven-local-repo
+ workspace: maven-local-m2
+---
+apiVersion: tekton.dev/v1beta1
+kind: PipelineRun
+metadata:
+ name: maven-test-pipeline-run
+spec:
+ pipelineRef:
+ name: maven-test-pipeline
+ workspaces:
+ - name: maven-settings
+ emptyDir: {}
+ - name: shared-workspace
+ persistentvolumeclaim:
+ claimName: maven-source-pvc
+ - name: maven-local-m2
+ persistentvolumeclaim:
+ claimName: maven-local-m2-pvc
+```
+
+---
+
+### With Custom Maven Params
+
+```yaml
+apiVersion: tekton.dev/v1beta1
+kind: Pipeline
+metadata:
+ name: maven-test-pipeline
+spec:
+ workspaces:
+ - name: shared-workspace
+ - name: maven-settings
+ - name: maven-local-m2
+ tasks:
+ - name: fetch-repository
+ taskRef:
+ name: git-clone
+ workspaces:
+ - name: output
+ workspace: shared-workspace
+ params:
+ - name: url
+ value: https://github.com/redhat-developer-demos/tekton-tutorial
+ - name: subdirectory
+ value: ""
+ - name: deleteExisting
+ value: "true"
+ - name: maven-run
+ taskRef:
+ name: maven
+ runAfter:
+ - fetch-repository
+ params:
+ - name: MAVEN_MIRROR_URL
+ value: http://repo1.maven.org/maven2
+ - name: CONTEXT_DIR
+ value: "apps/greeter/java/quarkus"
+ - name: GOALS
+ value:
+ - -DskipTests
+ - clean
+ - package
+ workspaces:
+ - name: maven-settings
+ workspace: maven-settings
+ - name: source
+ workspace: shared-workspace
+ - name: maven-local-repo
+ workspace: maven-local-m2
+
+```
+
+`PipelineRun` same as above in case of default values
+
+---
+
+### With Custom /.m2/settings.yaml
+
+A user provided custom `settings.xml` can be used with the Maven Task. To do this we need to mount the `settings.xml` on the Maven Task.
+Following steps demonstrate the use of a ConfigMap to mount a custom `settings.xml`.
+
+1. create configmap
+
+```yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: custom-maven-settings
+data:
+ settings.xml: |
+
+
+
+
+ maven.org
+ Default mirror
+ http://repo1.maven.org/maven2
+ central
+
+
+
+```
+
+or
+
+```bash
+oc create configmap custom-maven-settings --from-file=settings.xml
+```
+
+2. create `Pipeline` and `PipelineRun`
+
+```yaml
+apiVersion: tekton.dev/v1beta1
+kind: Pipeline
+metadata:
+ name: maven-test-pipeline
+spec:
+ workspaces:
+ - name: shared-workspace
+ - name: maven-settings
+ - name: maven-local-m2
+ tasks:
+ - name: fetch-repository
+ taskRef:
+ name: git-clone
+ workspaces:
+ - name: output
+ workspace: shared-workspace
+ params:
+ - name: url
+ value: https://github.com/redhat-developer-demos/tekton-tutorial
+ - name: subdirectory
+ value: ""
+ - name: deleteExisting
+ value: "true"
+ - name: maven-run
+ taskRef:
+ name: maven
+ runAfter:
+ - fetch-repository
+ params:
+ - name: CONTEXT_DIR
+ value: "apps/greeter/java/quarkus"
+ - name: GOALS
+ value:
+ - -DskipTests
+ - clean
+ - package
+ workspaces:
+ - name: maven-settings
+ workspace: maven-settings
+ - name: source
+ workspace: shared-workspace
+ - name: maven-local-repo
+ workspace: maven-local-m2
+
+---
+apiVersion: tekton.dev/v1beta1
+kind: PipelineRun
+metadata:
+ name: maven-test-pipeline-run
+spec:
+ pipelineRef:
+ name: maven-test-pipeline
+ workspaces:
+ - name: maven-settings
+ configMap:
+ name: custom-maven-settings
+ - name: shared-workspace
+ persistentvolumeclaim:
+ claimName: maven-source-pvc
+ - name: maven-local-m2
+ persistentvolumeclaim:
+ claimName: maven-local-m2-pvc
+```
diff --git a/task/maven/0.4/maven.yaml b/task/maven/0.4/maven.yaml
new file mode 100644
index 0000000000..45afbf8fdc
--- /dev/null
+++ b/task/maven/0.4/maven.yaml
@@ -0,0 +1,158 @@
+apiVersion: tekton.dev/v1beta1
+kind: Task
+metadata:
+ name: maven
+ labels:
+ app.kubernetes.io/version: "0.4"
+ annotations:
+ tekton.dev/pipelines.minVersion: "0.17.0"
+ tekton.dev/categories: Build Tools
+ tekton.dev/tags: build-tool
+ tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le"
+spec:
+ description: >-
+ This Task can be used to run a Maven build. It uses a workspace to store m2 local repo.
+
+ workspaces:
+ - name: source
+ description: The workspace consisting of maven project.
+ - name: maven-settings
+ description: >-
+ The workspace consisting of the custom maven settings
+ provided by the user.
+ - name: maven-local-repo
+ description: Local repo (m2) workspace
+ optional: true
+ params:
+ - name: MAVEN_IMAGE
+ type: string
+ description: Maven base image
+ default: gcr.io/cloud-builders/mvn@sha256:57523fc43394d6d9d2414ee8d1c85ed7a13460cbb268c3cd16d28cfb3859e641 #tag: latest
+ - name: MAVEN_COMMAND
+ description: Maven command to execute, you could use the maven wrapper over here.
+ type: string
+ default: "/usr/bin/mvn"
+ - name: GOALS
+ description: maven goals to run
+ type: array
+ default:
+ - "package"
+ - name: MAVEN_MIRROR_URL
+ description: The Maven repository mirror url
+ type: string
+ default: ""
+ - name: SERVER_USER
+ description: The username for the server
+ type: string
+ default: ""
+ - name: SERVER_PASSWORD
+ description: The password for the server
+ type: string
+ default: ""
+ - name: PROXY_USER
+ description: The username for the proxy server
+ type: string
+ default: ""
+ - name: PROXY_PASSWORD
+ description: The password for the proxy server
+ type: string
+ default: ""
+ - name: PROXY_PORT
+ description: Port number for the proxy server
+ type: string
+ default: ""
+ - name: PROXY_HOST
+ description: Proxy server Host
+ type: string
+ default: ""
+ - name: PROXY_NON_PROXY_HOSTS
+ description: Non proxy server host
+ type: string
+ default: ""
+ - name: PROXY_PROTOCOL
+ description: Protocol for the proxy ie http or https
+ type: string
+ default: "http"
+ - name: CONTEXT_DIR
+ type: string
+ description: >-
+ The context directory within the repository for sources on
+ which we want to execute maven goals.
+ default: "."
+ steps:
+ - name: mvn-settings
+ image: registry.access.redhat.com/ubi8/ubi-minimal:8.8
+ script: |
+ #!/usr/bin/env bash
+
+ [[ -f $(workspaces.maven-settings.path)/settings.xml ]] && \
+ echo "using existing $(workspaces.maven-settings.path)/settings.xml" && exit 0
+
+ cat > "$(workspaces.maven-settings.path)/settings.xml" <
+
+
+
+
+
+
+
+
+
+
+
+
+
+ EOF
+
+ xml=""
+ if [ -n "$(params.PROXY_HOST)" ] && [ -n "$(params.PROXY_PORT)" ]; then
+ xml="\
+ genproxy\
+ true\
+ $(params.PROXY_PROTOCOL)\
+ $(params.PROXY_HOST)\
+ $(params.PROXY_PORT)"
+ if [ -n "$(params.PROXY_USER)" ] && [ -n "$(params.PROXY_PASSWORD)" ]; then
+ xml="$xml\
+ $(params.PROXY_USER)\
+ $(params.PROXY_PASSWORD)"
+ fi
+ if [ -n "$(params.PROXY_NON_PROXY_HOSTS)" ]; then
+ xml="$xml\
+ $(params.PROXY_NON_PROXY_HOSTS)"
+ fi
+ xml="$xml\
+ "
+ sed -i "s||$xml|" "$(workspaces.maven-settings.path)/settings.xml"
+ fi
+
+ if [ -n "$(params.SERVER_USER)" ] && [ -n "$(params.SERVER_PASSWORD)" ]; then
+ xml="\
+ serverid"
+ xml="$xml\
+ $(params.SERVER_USER)\
+ $(params.SERVER_PASSWORD)"
+ xml="$xml\
+ "
+ sed -i "s||$xml|" "$(workspaces.maven-settings.path)/settings.xml"
+ fi
+
+ if [ -n "$(params.MAVEN_MIRROR_URL)" ]; then
+ xml=" \
+ mirror.default\
+ $(params.MAVEN_MIRROR_URL)\
+ central\
+ "
+ sed -i "s||$xml|" "$(workspaces.maven-settings.path)/settings.xml"
+ fi
+
+ - name: mvn-goals
+ image: $(params.MAVEN_IMAGE)
+ workingDir: $(workspaces.source.path)/$(params.CONTEXT_DIR)
+ command: ["$(params.MAVEN_COMMAND)"]
+ args:
+ - -s
+ - $(workspaces.maven-settings.path)/settings.xml
+ - "$(params.GOALS)"
+ - '-Dmaven.repo.local=$(workspaces.maven-local-repo.path)/.m2'
\ No newline at end of file
diff --git a/task/maven/0.4/tests/pre-apply-task-hook.sh b/task/maven/0.4/tests/pre-apply-task-hook.sh
new file mode 100755
index 0000000000..64f2208fb8
--- /dev/null
+++ b/task/maven/0.4/tests/pre-apply-task-hook.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+# Add git-clone
+add_task git-clone latest
diff --git a/task/maven/0.4/tests/resources.yaml b/task/maven/0.4/tests/resources.yaml
new file mode 100644
index 0000000000..23f1a4363a
--- /dev/null
+++ b/task/maven/0.4/tests/resources.yaml
@@ -0,0 +1,22 @@
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: maven-source-pvc
+spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 500Mi
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: maven-local-m2-pvc
+spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 3Gi
diff --git a/task/maven/0.4/tests/run.yaml b/task/maven/0.4/tests/run.yaml
new file mode 100644
index 0000000000..e681adc128
--- /dev/null
+++ b/task/maven/0.4/tests/run.yaml
@@ -0,0 +1,81 @@
+---
+apiVersion: tekton.dev/v1beta1
+kind: Pipeline
+metadata:
+ name: maven-test-pipeline
+spec:
+ workspaces:
+ - name: shared-workspace
+ - name: maven-settings
+ - name: maven-local-m2
+ tasks:
+ - name: fetch-repository
+ taskRef:
+ name: git-clone
+ workspaces:
+ - name: output
+ workspace: shared-workspace
+ params:
+ - name: url
+ value: https://github.com/vinamra28/tekton-tutorial-rh
+ - name: subdirectory
+ value: ""
+ - name: deleteExisting
+ value: "true"
+ - name: maven-run-build-1
+ taskRef:
+ name: maven
+ runAfter:
+ - fetch-repository
+ params:
+ - name: CONTEXT_DIR
+ value: "apps/greeter/java/quarkus"
+ - name: GOALS
+ value:
+ - -DskipTests
+ - clean
+ - package
+ workspaces:
+ - name: maven-settings
+ workspace: maven-settings
+ - name: source
+ workspace: shared-workspace
+ - name: maven-local-repo
+ workspace: maven-local-m2
+ - name: maven-run-build-2
+ taskRef:
+ name: maven
+ runAfter:
+ - maven-run-build-1
+ params:
+ - name: CONTEXT_DIR
+ value: "apps/greeter/java/quarkus"
+ - name: GOALS
+ value:
+ - -DskipTests
+ - clean
+ - package
+ workspaces:
+ - name: maven-settings
+ workspace: maven-settings
+ - name: source
+ workspace: shared-workspace
+ - name: maven-local-repo
+ workspace: maven-local-m2
+---
+apiVersion: tekton.dev/v1beta1
+kind: PipelineRun
+metadata:
+ name: maven-test-pipeline-run
+spec:
+ pipelineRef:
+ name: maven-test-pipeline
+ workspaces:
+ - name: maven-settings
+ emptyDir: {}
+ - name: shared-workspace
+ persistentvolumeclaim:
+ claimName: maven-source-pvc
+ - name: maven-local-m2
+ persistentvolumeclaim:
+ claimName: maven-local-m2-pvc