You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by as...@apache.org on 2019/11/04 16:10:25 UTC

[camel-k] 01/38: feat(quarkus): Initial Quarkus support

This is an automated email from the ASF dual-hosted git repository.

astefanutti pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit bbf9b3ad1f1211c09d8aaedb01aa294877317965
Author: Antonin Stefanutti <an...@stefanutti.fr>
AuthorDate: Tue Oct 15 19:20:58 2019 +0200

    feat(quarkus): Initial Quarkus support
---
 pkg/builder/builder_steps.go                       | 129 ++++-------
 pkg/builder/builder_steps_test.go                  | 171 +-------------
 pkg/builder/builder_utils.go                       |  65 ------
 pkg/builder/builder_utils_test.go                  |  87 -------
 pkg/builder/kaniko/kaniko.go                       |  10 +-
 pkg/builder/{builder_utils.go => runtime/main.go}  |  99 ++++----
 .../main_test.go}                                  | 251 ++++++---------------
 pkg/builder/runtime/quarkus.go                     | 142 ++++++++++++
 .../{kaniko/kaniko.go => runtime/runtime.go}       |  45 ++--
 pkg/builder/s2i/s2i.go                             |  10 +-
 pkg/trait/builder.go                               |  17 +-
 pkg/trait/dependencies.go                          |  45 ++--
 pkg/trait/dependencies_test.go                     |   5 +
 pkg/trait/environment.go                           |   8 +-
 pkg/trait/quarkus.go                               |  94 ++++++++
 pkg/trait/rest-dsl.go                              |   6 +-
 pkg/trait/trait_catalog.go                         |   6 +
 pkg/util/maven/maven.go                            |  11 +-
 pkg/util/maven/maven_types.go                      |   2 +
 19 files changed, 498 insertions(+), 705 deletions(-)

diff --git a/pkg/builder/builder_steps.go b/pkg/builder/builder_steps.go
index b46d0c2..3e935e3 100644
--- a/pkg/builder/builder_steps.go
+++ b/pkg/builder/builder_steps.go
@@ -19,23 +19,17 @@ package builder
 
 import (
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path"
 	"reflect"
 	"strings"
 
-	"github.com/apache/camel-k/pkg/util/kubernetes"
-
 	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"github.com/apache/camel-k/pkg/util/maven"
 	"github.com/apache/camel-k/pkg/util/tar"
-
-	yaml2 "gopkg.in/yaml.v2"
-
-	"github.com/pkg/errors"
 )
 
 var stepsByID = make(map[string]Step)
@@ -45,21 +39,15 @@ func init() {
 }
 
 type steps struct {
-	GenerateProject         Step
 	GenerateProjectSettings Step
 	InjectDependencies      Step
 	SanitizeDependencies    Step
-	ComputeDependencies     Step
 	StandardPackager        Step
 	IncrementalPackager     Step
 }
 
 // Steps --
 var Steps = steps{
-	GenerateProject: NewStep(
-		ProjectGenerationPhase,
-		generateProject,
-	),
 	GenerateProjectSettings: NewStep(
 		ProjectGenerationPhase+1,
 		generateProjectSettings,
@@ -72,10 +60,6 @@ var Steps = steps{
 		ProjectGenerationPhase+3,
 		sanitizeDependencies,
 	),
-	ComputeDependencies: NewStep(
-		ProjectBuildPhase,
-		computeDependencies,
-	),
 	StandardPackager: NewStep(
 		ApplicationPackagePhase,
 		standardPackager,
@@ -86,6 +70,14 @@ var Steps = steps{
 	),
 }
 
+// DefaultSteps --
+var DefaultSteps = []Step{
+	Steps.GenerateProjectSettings,
+	Steps.InjectDependencies,
+	Steps.SanitizeDependencies,
+	Steps.IncrementalPackager,
+}
+
 // RegisterSteps --
 func RegisterSteps(steps interface{}) {
 	v := reflect.ValueOf(steps)
@@ -112,17 +104,39 @@ func registerStep(steps ...Step) {
 	}
 }
 
-// generateProject --
-func generateProject(ctx *Context) error {
-	p, err := NewMavenProject(ctx)
+// generateProjectSettings --
+func generateProjectSettings(ctx *Context) error {
+	val, err := kubernetes.ResolveValueSource(ctx.C, ctx.Client, ctx.Namespace, &ctx.Build.Platform.Build.Maven.Settings)
 	if err != nil {
 		return err
 	}
+	if val != "" {
+		ctx.Maven.SettingsData = []byte(val)
+	}
 
-	ctx.Maven.Project = p
+	return nil
+}
 
+func injectDependencies(ctx *Context) error {
+	// Add dependencies from build
 	for _, d := range ctx.Build.Dependencies {
 		switch {
+		case strings.HasPrefix(d, "bom:"):
+			mid := strings.TrimPrefix(d, "bom:")
+			gav := strings.Replace(mid, "/", ":", -1)
+
+			d, err := maven.ParseGAV(gav)
+			if err != nil {
+				return err
+			}
+
+			ctx.Maven.Project.DependencyManagement.Dependencies = append(ctx.Maven.Project.DependencyManagement.Dependencies, maven.Dependency{
+				GroupID:    d.GroupID,
+				ArtifactID: d.ArtifactID,
+				Version:    d.Version,
+				Type:       "pom",
+				Scope:      "import",
+			})
 		case strings.HasPrefix(d, "camel:"):
 			artifactID := strings.TrimPrefix(d, "camel:")
 
@@ -144,33 +158,12 @@ func generateProject(ctx *Context) error {
 			gav := strings.Replace(mid, "/", ":", -1)
 
 			ctx.Maven.Project.AddEncodedDependencyGAV(gav)
-		case strings.HasPrefix(d, "bom:"):
-			// no-op
 		default:
 			return fmt.Errorf("unknown dependency type: %s", d)
 		}
 	}
 
-	return nil
-}
-
-// generateProjectSettings --
-func generateProjectSettings(ctx *Context) error {
-	val, err := kubernetes.ResolveValueSource(ctx.C, ctx.Client, ctx.Namespace, &ctx.Build.Platform.Build.Maven.Settings)
-	if err != nil {
-		return err
-	}
-	if val != "" {
-		ctx.Maven.SettingsData = []byte(val)
-	}
-
-	return nil
-}
-
-func injectDependencies(ctx *Context) error {
-	//
 	// Add dependencies from catalog
-	//
 	deps := make([]maven.Dependency, len(ctx.Maven.Project.Dependencies))
 	copy(deps, ctx.Maven.Project.Dependencies)
 
@@ -195,9 +188,8 @@ func injectDependencies(ctx *Context) error {
 			}
 		}
 	}
-	//
-	// post process dependencies
-	//
+
+	// Post process dependencies
 	deps = make([]maven.Dependency, len(ctx.Maven.Project.Dependencies))
 	copy(deps, ctx.Maven.Project.Dependencies)
 
@@ -243,49 +235,7 @@ func sanitizeDependencies(ctx *Context) error {
 	return nil
 }
 
-func computeDependencies(ctx *Context) error {
-	mc := maven.NewContext(path.Join(ctx.Path, "maven"), ctx.Maven.Project)
-	mc.SettingsContent = ctx.Maven.SettingsData
-	mc.LocalRepository = ctx.Build.Platform.Build.LocalRepository
-	mc.Timeout = ctx.Build.Platform.Build.Maven.Timeout.Duration
-	mc.AddArgumentf("org.apache.camel.k:camel-k-maven-plugin:%s:generate-dependency-list", ctx.Catalog.RuntimeVersion)
-
-	if err := maven.Run(mc); err != nil {
-		return errors.Wrap(err, "failure while determining classpath")
-	}
-
-	dependencies := path.Join(mc.Path, "target", "dependencies.yaml")
-	content, err := ioutil.ReadFile(dependencies)
-	if err != nil {
-		return err
-	}
-
-	cp := make(map[string][]v1alpha1.Artifact)
-	err = yaml2.Unmarshal(content, &cp)
-	if err != nil {
-		return err
-	}
-
-	for _, e := range cp["dependencies"] {
-		_, fileName := path.Split(e.Location)
-
-		gav, err := maven.ParseGAV(e.ID)
-		if err != nil {
-			return nil
-		}
-
-		ctx.Artifacts = append(ctx.Artifacts, v1alpha1.Artifact{
-			ID:       e.ID,
-			Location: e.Location,
-			Target:   path.Join("dependencies", gav.GroupID+"."+fileName),
-		})
-	}
-
-	return nil
-}
-
-// ArtifactsSelector --
-type ArtifactsSelector func(ctx *Context) error
+type artifactsSelector func(ctx *Context) error
 
 func standardPackager(ctx *Context) error {
 	return packager(ctx, func(ctx *Context) error {
@@ -330,8 +280,7 @@ func incrementalPackager(ctx *Context) error {
 	})
 }
 
-// ClassPathPackager --
-func packager(ctx *Context, selector ArtifactsSelector) error {
+func packager(ctx *Context, selector artifactsSelector) error {
 	err := selector(ctx)
 	if err != nil {
 		return err
diff --git a/pkg/builder/builder_steps_test.go b/pkg/builder/builder_steps_test.go
index d21564d..c950477 100644
--- a/pkg/builder/builder_steps_test.go
+++ b/pkg/builder/builder_steps_test.go
@@ -25,7 +25,6 @@ import (
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/util/cancellable"
-	"github.com/apache/camel-k/pkg/util/maven"
 	"github.com/apache/camel-k/pkg/util/test"
 
 	"github.com/stretchr/testify/assert"
@@ -50,63 +49,6 @@ func TestRegisterDuplicatedSteps(t *testing.T) {
 	})
 }
 
-func TestGenerateJvmProject(t *testing.T) {
-	catalog, err := test.DefaultCatalog()
-	assert.Nil(t, err)
-
-	ctx := Context{
-		Catalog: catalog,
-		Build: v1alpha1.BuildSpec{
-			RuntimeVersion: catalog.RuntimeVersion,
-			Platform: v1alpha1.IntegrationPlatformSpec{
-				Build: v1alpha1.IntegrationPlatformBuildSpec{
-					CamelVersion: catalog.Version,
-				},
-			},
-			Dependencies: []string{
-				"camel-k:runtime-main",
-			},
-		},
-	}
-
-	err = generateProject(&ctx)
-	assert.Nil(t, err)
-	err = injectDependencies(&ctx)
-	assert.Nil(t, err)
-
-	assert.ElementsMatch(
-		t,
-		ctx.Maven.Project.DependencyManagement.Dependencies,
-		[]maven.Dependency{
-			{
-				GroupID:    "org.apache.camel",
-				ArtifactID: "camel-bom",
-				Version:    catalog.Version,
-				Type:       "pom",
-				Scope:      "import",
-			},
-			{
-				GroupID:    "org.apache.camel.k",
-				ArtifactID: "camel-k-runtime-bom",
-				Version:    catalog.RuntimeVersion,
-				Type:       "pom",
-				Scope:      "import",
-			},
-		},
-	)
-
-	assert.ElementsMatch(
-		t,
-		ctx.Maven.Project.Dependencies,
-		[]maven.Dependency{
-			{GroupID: "org.apache.camel.k", ArtifactID: "camel-k-runtime-main"},
-			{GroupID: "org.apache.camel", ArtifactID: "camel-core-engine"},
-			{GroupID: "org.apache.camel", ArtifactID: "camel-main"},
-			{GroupID: "org.apache.camel", ArtifactID: "camel-properties"},
-		},
-	)
-}
-
 func TestMavenSettingsFromConfigMap(t *testing.T) {
 	catalog, err := test.DefaultCatalog()
 	assert.Nil(t, err)
@@ -153,7 +95,7 @@ func TestMavenSettingsFromConfigMap(t *testing.T) {
 		},
 	}
 
-	err = generateProjectSettings(&ctx)
+	err = Steps.GenerateProjectSettings.Execute(&ctx)
 	assert.Nil(t, err)
 
 	assert.Equal(t, []byte("setting-data"), ctx.Maven.SettingsData)
@@ -205,121 +147,12 @@ func TestMavenSettingsFromSecret(t *testing.T) {
 		},
 	}
 
-	err = generateProjectSettings(&ctx)
+	err = Steps.GenerateProjectSettings.Execute(&ctx)
 	assert.Nil(t, err)
 
 	assert.Equal(t, []byte("setting-data"), ctx.Maven.SettingsData)
 }
 
-func TestGenerateGroovyProject(t *testing.T) {
-	catalog, err := test.DefaultCatalog()
-	assert.Nil(t, err)
-
-	ctx := Context{
-		Catalog: catalog,
-		Build: v1alpha1.BuildSpec{
-			RuntimeVersion: catalog.RuntimeVersion,
-			Platform: v1alpha1.IntegrationPlatformSpec{
-				Build: v1alpha1.IntegrationPlatformBuildSpec{
-					CamelVersion: catalog.Version,
-				},
-			},
-			Dependencies: []string{
-				"camel-k:runtime-main",
-				"camel-k:loader-groovy",
-			},
-		},
-	}
-
-	err = generateProject(&ctx)
-	assert.Nil(t, err)
-	err = injectDependencies(&ctx)
-	assert.Nil(t, err)
-
-	assert.ElementsMatch(
-		t,
-		ctx.Maven.Project.DependencyManagement.Dependencies,
-		[]maven.Dependency{
-			{
-				GroupID:    "org.apache.camel",
-				ArtifactID: "camel-bom",
-				Version:    catalog.Version,
-				Type:       "pom",
-				Scope:      "import",
-			},
-			{
-				GroupID:    "org.apache.camel.k",
-				ArtifactID: "camel-k-runtime-bom",
-				Version:    catalog.RuntimeVersion,
-				Type:       "pom",
-				Scope:      "import",
-			},
-		},
-	)
-
-	assert.ElementsMatch(
-		t,
-		ctx.Maven.Project.Dependencies,
-		[]maven.Dependency{
-			{GroupID: "org.apache.camel.k", ArtifactID: "camel-k-runtime-main"},
-			{GroupID: "org.apache.camel.k", ArtifactID: "camel-k-loader-groovy"},
-			{GroupID: "org.apache.camel", ArtifactID: "camel-core-engine"},
-			{GroupID: "org.apache.camel", ArtifactID: "camel-main"},
-			{GroupID: "org.apache.camel", ArtifactID: "camel-groovy"},
-			{GroupID: "org.apache.camel", ArtifactID: "camel-properties"},
-			{GroupID: "org.apache.camel", ArtifactID: "camel-endpointdsl"},
-		},
-	)
-}
-
-func TestSanitizeDependencies(t *testing.T) {
-	catalog, err := test.DefaultCatalog()
-	assert.Nil(t, err)
-
-	ctx := Context{
-		Catalog: catalog,
-		Build: v1alpha1.BuildSpec{
-			RuntimeVersion: catalog.RuntimeVersion,
-			Platform: v1alpha1.IntegrationPlatformSpec{
-				Build: v1alpha1.IntegrationPlatformBuildSpec{
-					CamelVersion: catalog.Version,
-				},
-			},
-			Dependencies: []string{
-				"camel:undertow",
-				"mvn:org.apache.camel/camel-core/2.18.0",
-				"mvn:org.apache.camel.k/camel-k-runtime-main/1.0.0",
-				"mvn:com.mycompany/my-dep/1.2.3",
-			},
-		},
-	}
-
-	err = generateProject(&ctx)
-	assert.Nil(t, err)
-	err = injectDependencies(&ctx)
-	assert.Nil(t, err)
-	err = sanitizeDependencies(&ctx)
-	assert.Nil(t, err)
-
-	assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{
-		GroupID:    "org.apache.camel.k",
-		ArtifactID: "camel-k-runtime-main",
-	})
-	assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{
-		GroupID:    "org.apache.camel",
-		ArtifactID: "camel-core",
-	})
-	assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{
-		GroupID:    "org.apache.camel",
-		ArtifactID: "camel-undertow",
-	})
-	assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{
-		GroupID:    "com.mycompany",
-		ArtifactID: "my-dep",
-		Version:    "1.2.3",
-	})
-}
-
 func TestListPublishedImages(t *testing.T) {
 	catalog, err := test.DefaultCatalog()
 	assert.Nil(t, err)
diff --git a/pkg/builder/builder_utils.go b/pkg/builder/builder_utils.go
index e6516dd..5098e5a 100644
--- a/pkg/builder/builder_utils.go
+++ b/pkg/builder/builder_utils.go
@@ -18,12 +18,7 @@ limitations under the License.
 package builder
 
 import (
-	"strings"
-
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
-	"github.com/apache/camel-k/pkg/util/camel"
-	"github.com/apache/camel-k/pkg/util/defaults"
-	"github.com/apache/camel-k/pkg/util/maven"
 )
 
 // StepIDsFor --
@@ -44,63 +39,3 @@ func artifactIDs(artifacts []v1alpha1.Artifact) []string {
 
 	return result
 }
-
-// NewMavenProject --
-func NewMavenProject(ctx *Context) (maven.Project, error) {
-	//
-	// Catalog
-	//
-	if ctx.Catalog == nil {
-		c, err := camel.LoadCatalog(ctx.C, ctx.Client, ctx.Namespace, ctx.Build.Platform.Build.CamelVersion, ctx.Build.Platform.Build.RuntimeVersion)
-		if err != nil {
-			return maven.Project{}, err
-		}
-
-		ctx.Catalog = c
-	}
-
-	p := maven.NewProjectWithGAV("org.apache.camel.k.integration", "camel-k-integration", defaults.Version)
-	p.Properties = ctx.Build.Platform.Build.Properties
-	p.DependencyManagement = &maven.DependencyManagement{Dependencies: make([]maven.Dependency, 0)}
-	p.Dependencies = make([]maven.Dependency, 0)
-
-	//
-	// DependencyManagement
-	//
-	p.DependencyManagement.Dependencies = append(p.DependencyManagement.Dependencies, maven.Dependency{
-		GroupID:    "org.apache.camel",
-		ArtifactID: "camel-bom",
-		Version:    ctx.Catalog.Version,
-		Type:       "pom",
-		Scope:      "import",
-	})
-	p.DependencyManagement.Dependencies = append(p.DependencyManagement.Dependencies, maven.Dependency{
-		GroupID:    "org.apache.camel.k",
-		ArtifactID: "camel-k-runtime-bom",
-		Version:    ctx.Catalog.RuntimeVersion,
-		Type:       "pom",
-		Scope:      "import",
-	})
-
-	for _, d := range ctx.Build.Dependencies {
-		if strings.HasPrefix(d, "bom:") {
-			mid := strings.TrimPrefix(d, "bom:")
-			gav := strings.Replace(mid, "/", ":", -1)
-
-			d, err := maven.ParseGAV(gav)
-			if err != nil {
-				return maven.Project{}, err
-			}
-
-			p.DependencyManagement.Dependencies = append(p.DependencyManagement.Dependencies, maven.Dependency{
-				GroupID:    d.GroupID,
-				ArtifactID: d.ArtifactID,
-				Version:    d.Version,
-				Type:       "pom",
-				Scope:      "import",
-			})
-		}
-	}
-
-	return p, nil
-}
diff --git a/pkg/builder/builder_utils_test.go b/pkg/builder/builder_utils_test.go
deleted file mode 100644
index 951d035..0000000
--- a/pkg/builder/builder_utils_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-   http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package builder
-
-import (
-	"testing"
-
-	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
-	"github.com/apache/camel-k/pkg/util/maven"
-	"github.com/apache/camel-k/pkg/util/test"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestNewProject(t *testing.T) {
-	catalog, err := test.DefaultCatalog()
-	assert.Nil(t, err)
-
-	ctx := Context{
-		Catalog: catalog,
-		Build: v1alpha1.BuildSpec{
-			RuntimeVersion: catalog.RuntimeVersion,
-			Platform: v1alpha1.IntegrationPlatformSpec{
-				Build: v1alpha1.IntegrationPlatformBuildSpec{
-					CamelVersion: catalog.Version,
-				},
-			},
-			Dependencies: []string{
-				"camel-k:runtime-main",
-				"bom:my.company/my-artifact-1/1.0.0",
-				"bom:my.company/my-artifact-2/2.0.0",
-			},
-		},
-	}
-
-	err = generateProject(&ctx)
-	assert.Nil(t, err)
-	assert.ElementsMatch(
-		t,
-		ctx.Maven.Project.DependencyManagement.Dependencies,
-		[]maven.Dependency{
-			{
-				GroupID:    "org.apache.camel",
-				ArtifactID: "camel-bom",
-				Version:    ctx.Catalog.Version,
-				Type:       "pom",
-				Scope:      "import",
-			},
-			{
-				GroupID:    "org.apache.camel.k",
-				ArtifactID: "camel-k-runtime-bom",
-				Version:    catalog.RuntimeVersion,
-				Type:       "pom",
-				Scope:      "import",
-			},
-			{
-				GroupID:    "my.company",
-				ArtifactID: "my-artifact-1",
-				Version:    "1.0.0",
-				Type:       "pom",
-				Scope:      "import",
-			},
-			{
-				GroupID:    "my.company",
-				ArtifactID: "my-artifact-2",
-				Version:    "2.0.0",
-				Type:       "pom",
-				Scope:      "import",
-			},
-		},
-	)
-}
diff --git a/pkg/builder/kaniko/kaniko.go b/pkg/builder/kaniko/kaniko.go
index f5e53cb..efc0291 100644
--- a/pkg/builder/kaniko/kaniko.go
+++ b/pkg/builder/kaniko/kaniko.go
@@ -37,14 +37,8 @@ var Steps = steps{
 	),
 }
 
-// DefaultSteps --
-var DefaultSteps = []builder.Step{
-	builder.Steps.GenerateProject,
-	builder.Steps.GenerateProjectSettings,
-	builder.Steps.InjectDependencies,
-	builder.Steps.SanitizeDependencies,
-	builder.Steps.ComputeDependencies,
-	builder.Steps.IncrementalPackager,
+// KanikoSteps --
+var KanikoSteps = []builder.Step{
 	Steps.Publisher,
 }
 
diff --git a/pkg/builder/builder_utils.go b/pkg/builder/runtime/main.go
similarity index 58%
copy from pkg/builder/builder_utils.go
copy to pkg/builder/runtime/main.go
index e6516dd..dbf6668 100644
--- a/pkg/builder/builder_utils.go
+++ b/pkg/builder/runtime/main.go
@@ -15,45 +15,35 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package builder
+package runtime
 
 import (
-	"strings"
+	"io/ioutil"
+	"path"
+
+	"github.com/pkg/errors"
+
+	yaml2 "gopkg.in/yaml.v2"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/builder"
 	"github.com/apache/camel-k/pkg/util/camel"
 	"github.com/apache/camel-k/pkg/util/defaults"
 	"github.com/apache/camel-k/pkg/util/maven"
 )
 
-// StepIDsFor --
-func StepIDsFor(steps ...Step) []string {
-	IDs := make([]string, 0)
-	for _, step := range steps {
-		IDs = append(IDs, step.ID())
-	}
-	return IDs
+// MainSteps --
+var MainSteps = []builder.Step{
+	Steps.GenerateProject,
+	Steps.ComputeDependencies,
 }
 
-func artifactIDs(artifacts []v1alpha1.Artifact) []string {
-	result := make([]string, 0, len(artifacts))
-
-	for _, a := range artifacts {
-		result = append(result, a.ID)
-	}
-
-	return result
-}
-
-// NewMavenProject --
-func NewMavenProject(ctx *Context) (maven.Project, error) {
-	//
+func generateProject(ctx *builder.Context) error {
 	// Catalog
-	//
 	if ctx.Catalog == nil {
 		c, err := camel.LoadCatalog(ctx.C, ctx.Client, ctx.Namespace, ctx.Build.Platform.Build.CamelVersion, ctx.Build.Platform.Build.RuntimeVersion)
 		if err != nil {
-			return maven.Project{}, err
+			return err
 		}
 
 		ctx.Catalog = c
@@ -64,9 +54,7 @@ func NewMavenProject(ctx *Context) (maven.Project, error) {
 	p.DependencyManagement = &maven.DependencyManagement{Dependencies: make([]maven.Dependency, 0)}
 	p.Dependencies = make([]maven.Dependency, 0)
 
-	//
 	// DependencyManagement
-	//
 	p.DependencyManagement.Dependencies = append(p.DependencyManagement.Dependencies, maven.Dependency{
 		GroupID:    "org.apache.camel",
 		ArtifactID: "camel-bom",
@@ -82,25 +70,48 @@ func NewMavenProject(ctx *Context) (maven.Project, error) {
 		Scope:      "import",
 	})
 
-	for _, d := range ctx.Build.Dependencies {
-		if strings.HasPrefix(d, "bom:") {
-			mid := strings.TrimPrefix(d, "bom:")
-			gav := strings.Replace(mid, "/", ":", -1)
-
-			d, err := maven.ParseGAV(gav)
-			if err != nil {
-				return maven.Project{}, err
-			}
-
-			p.DependencyManagement.Dependencies = append(p.DependencyManagement.Dependencies, maven.Dependency{
-				GroupID:    d.GroupID,
-				ArtifactID: d.ArtifactID,
-				Version:    d.Version,
-				Type:       "pom",
-				Scope:      "import",
-			})
+	ctx.Maven.Project = p
+
+	return nil
+}
+
+func computeDependencies(ctx *builder.Context) error {
+	mc := maven.NewContext(path.Join(ctx.Path, "maven"), ctx.Maven.Project)
+	mc.SettingsContent = ctx.Maven.SettingsData
+	mc.LocalRepository = ctx.Build.Platform.Build.LocalRepository
+	mc.Timeout = ctx.Build.Platform.Build.Maven.Timeout.Duration
+	mc.AddArgumentf("org.apache.camel.k:camel-k-maven-plugin:%s:generate-dependency-list", ctx.Catalog.RuntimeVersion)
+
+	if err := maven.Run(mc); err != nil {
+		return errors.Wrap(err, "failure while determining classpath")
+	}
+
+	dependencies := path.Join(mc.Path, "target", "dependencies.yaml")
+	content, err := ioutil.ReadFile(dependencies)
+	if err != nil {
+		return err
+	}
+
+	cp := make(map[string][]v1alpha1.Artifact)
+	err = yaml2.Unmarshal(content, &cp)
+	if err != nil {
+		return err
+	}
+
+	for _, e := range cp["dependencies"] {
+		_, fileName := path.Split(e.Location)
+
+		gav, err := maven.ParseGAV(e.ID)
+		if err != nil {
+			return nil
 		}
+
+		ctx.Artifacts = append(ctx.Artifacts, v1alpha1.Artifact{
+			ID:       e.ID,
+			Location: e.Location,
+			Target:   path.Join("dependencies", gav.GroupID+"."+fileName),
+		})
 	}
 
-	return p, nil
+	return nil
 }
diff --git a/pkg/builder/builder_steps_test.go b/pkg/builder/runtime/main_test.go
similarity index 55%
copy from pkg/builder/builder_steps_test.go
copy to pkg/builder/runtime/main_test.go
index d21564d..e98b813 100644
--- a/pkg/builder/builder_steps_test.go
+++ b/pkg/builder/runtime/main_test.go
@@ -15,46 +15,24 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package builder
+package runtime
 
 import (
 	"testing"
 
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"github.com/stretchr/testify/assert"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
-	"github.com/apache/camel-k/pkg/util/cancellable"
+	"github.com/apache/camel-k/pkg/builder"
 	"github.com/apache/camel-k/pkg/util/maven"
 	"github.com/apache/camel-k/pkg/util/test"
-
-	"github.com/stretchr/testify/assert"
 )
 
-type testSteps struct {
-	TestStep Step
-}
-
-func TestRegisterDuplicatedSteps(t *testing.T) {
-	steps := testSteps{
-		TestStep: NewStep(
-			ApplicationPublishPhase,
-			func(context *Context) error {
-				return nil
-			},
-		),
-	}
-	RegisterSteps(steps)
-	assert.Panics(t, func() {
-		RegisterSteps(steps)
-	})
-}
-
-func TestGenerateJvmProject(t *testing.T) {
+func TestNewProject(t *testing.T) {
 	catalog, err := test.DefaultCatalog()
 	assert.Nil(t, err)
 
-	ctx := Context{
+	ctx := builder.Context{
 		Catalog: catalog,
 		Build: v1alpha1.BuildSpec{
 			RuntimeVersion: catalog.RuntimeVersion,
@@ -65,13 +43,15 @@ func TestGenerateJvmProject(t *testing.T) {
 			},
 			Dependencies: []string{
 				"camel-k:runtime-main",
+				"bom:my.company/my-artifact-1/1.0.0",
+				"bom:my.company/my-artifact-2/2.0.0",
 			},
 		},
 	}
 
-	err = generateProject(&ctx)
+	err = Steps.GenerateProject.Execute(&ctx)
 	assert.Nil(t, err)
-	err = injectDependencies(&ctx)
+	err = builder.Steps.InjectDependencies.Execute(&ctx)
 	assert.Nil(t, err)
 
 	assert.ElementsMatch(
@@ -81,7 +61,7 @@ func TestGenerateJvmProject(t *testing.T) {
 			{
 				GroupID:    "org.apache.camel",
 				ArtifactID: "camel-bom",
-				Version:    catalog.Version,
+				Version:    ctx.Catalog.Version,
 				Type:       "pom",
 				Scope:      "import",
 			},
@@ -92,130 +72,86 @@ func TestGenerateJvmProject(t *testing.T) {
 				Type:       "pom",
 				Scope:      "import",
 			},
-		},
-	)
-
-	assert.ElementsMatch(
-		t,
-		ctx.Maven.Project.Dependencies,
-		[]maven.Dependency{
-			{GroupID: "org.apache.camel.k", ArtifactID: "camel-k-runtime-main"},
-			{GroupID: "org.apache.camel", ArtifactID: "camel-core-engine"},
-			{GroupID: "org.apache.camel", ArtifactID: "camel-main"},
-			{GroupID: "org.apache.camel", ArtifactID: "camel-properties"},
-		},
-	)
-}
-
-func TestMavenSettingsFromConfigMap(t *testing.T) {
-	catalog, err := test.DefaultCatalog()
-	assert.Nil(t, err)
-
-	c, err := test.NewFakeClient(
-		&corev1.ConfigMap{
-			TypeMeta: metav1.TypeMeta{
-				APIVersion: "v1",
-				Kind:       "ConfigMap",
-			},
-			ObjectMeta: metav1.ObjectMeta{
-				Namespace: "ns",
-				Name:      "maven-settings",
+			{
+				GroupID:    "my.company",
+				ArtifactID: "my-artifact-1",
+				Version:    "1.0.0",
+				Type:       "pom",
+				Scope:      "import",
 			},
-			Data: map[string]string{
-				"settings.xml": "setting-data",
+			{
+				GroupID:    "my.company",
+				ArtifactID: "my-artifact-2",
+				Version:    "2.0.0",
+				Type:       "pom",
+				Scope:      "import",
 			},
 		},
 	)
+}
 
+func TestGenerateJvmProject(t *testing.T) {
+	catalog, err := test.DefaultCatalog()
 	assert.Nil(t, err)
 
-	ctx := Context{
-		Catalog:   catalog,
-		Client:    c,
-		Namespace: "ns",
+	ctx := builder.Context{
+		Catalog: catalog,
 		Build: v1alpha1.BuildSpec{
 			RuntimeVersion: catalog.RuntimeVersion,
 			Platform: v1alpha1.IntegrationPlatformSpec{
 				Build: v1alpha1.IntegrationPlatformBuildSpec{
 					CamelVersion: catalog.Version,
-					Maven: v1alpha1.MavenSpec{
-						Settings: v1alpha1.ValueSource{
-							ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
-								LocalObjectReference: corev1.LocalObjectReference{
-									Name: "maven-settings",
-								},
-								Key: "settings.xml",
-							},
-						},
-					},
 				},
 			},
+			Dependencies: []string{
+				"camel-k:runtime-main",
+			},
 		},
 	}
 
-	err = generateProjectSettings(&ctx)
+	err = Steps.GenerateProject.Execute(&ctx)
 	assert.Nil(t, err)
-
-	assert.Equal(t, []byte("setting-data"), ctx.Maven.SettingsData)
-}
-
-func TestMavenSettingsFromSecret(t *testing.T) {
-	catalog, err := test.DefaultCatalog()
+	err = builder.Steps.InjectDependencies.Execute(&ctx)
 	assert.Nil(t, err)
 
-	c, err := test.NewFakeClient(
-		&corev1.Secret{
-			TypeMeta: metav1.TypeMeta{
-				APIVersion: "v1",
-				Kind:       "Secret",
-			},
-			ObjectMeta: metav1.ObjectMeta{
-				Namespace: "ns",
-				Name:      "maven-settings",
+	assert.ElementsMatch(
+		t,
+		ctx.Maven.Project.DependencyManagement.Dependencies,
+		[]maven.Dependency{
+			{
+				GroupID:    "org.apache.camel",
+				ArtifactID: "camel-bom",
+				Version:    catalog.Version,
+				Type:       "pom",
+				Scope:      "import",
 			},
-			Data: map[string][]byte{
-				"settings.xml": []byte("setting-data"),
+			{
+				GroupID:    "org.apache.camel.k",
+				ArtifactID: "camel-k-runtime-bom",
+				Version:    catalog.RuntimeVersion,
+				Type:       "pom",
+				Scope:      "import",
 			},
 		},
 	)
 
-	assert.Nil(t, err)
-
-	ctx := Context{
-		Catalog:   catalog,
-		Client:    c,
-		Namespace: "ns",
-		Build: v1alpha1.BuildSpec{
-			RuntimeVersion: catalog.RuntimeVersion,
-			Platform: v1alpha1.IntegrationPlatformSpec{
-				Build: v1alpha1.IntegrationPlatformBuildSpec{
-					CamelVersion: catalog.Version,
-					Maven: v1alpha1.MavenSpec{
-						Settings: v1alpha1.ValueSource{
-							SecretKeyRef: &corev1.SecretKeySelector{
-								LocalObjectReference: corev1.LocalObjectReference{
-									Name: "maven-settings",
-								},
-								Key: "settings.xml",
-							},
-						},
-					},
-				},
-			},
+	assert.ElementsMatch(
+		t,
+		ctx.Maven.Project.Dependencies,
+		[]maven.Dependency{
+			{GroupID: "org.apache.camel.k", ArtifactID: "camel-k-runtime-main"},
+			{GroupID: "org.apache.camel", ArtifactID: "camel-core-engine"},
+			{GroupID: "org.apache.camel", ArtifactID: "camel-main"},
+			{GroupID: "org.apache.camel", ArtifactID: "camel-properties"},
 		},
-	}
-
-	err = generateProjectSettings(&ctx)
-	assert.Nil(t, err)
-
-	assert.Equal(t, []byte("setting-data"), ctx.Maven.SettingsData)
+	)
 }
 
 func TestGenerateGroovyProject(t *testing.T) {
 	catalog, err := test.DefaultCatalog()
 	assert.Nil(t, err)
 
-	ctx := Context{
+	ctx := builder.Context{
 		Catalog: catalog,
 		Build: v1alpha1.BuildSpec{
 			RuntimeVersion: catalog.RuntimeVersion,
@@ -231,9 +167,9 @@ func TestGenerateGroovyProject(t *testing.T) {
 		},
 	}
 
-	err = generateProject(&ctx)
+	err = Steps.GenerateProject.Execute(&ctx)
 	assert.Nil(t, err)
-	err = injectDependencies(&ctx)
+	err = builder.Steps.InjectDependencies.Execute(&ctx)
 	assert.Nil(t, err)
 
 	assert.ElementsMatch(
@@ -276,7 +212,7 @@ func TestSanitizeDependencies(t *testing.T) {
 	catalog, err := test.DefaultCatalog()
 	assert.Nil(t, err)
 
-	ctx := Context{
+	ctx := builder.Context{
 		Catalog: catalog,
 		Build: v1alpha1.BuildSpec{
 			RuntimeVersion: catalog.RuntimeVersion,
@@ -294,11 +230,11 @@ func TestSanitizeDependencies(t *testing.T) {
 		},
 	}
 
-	err = generateProject(&ctx)
+	err = Steps.GenerateProject.Execute(&ctx)
 	assert.Nil(t, err)
-	err = injectDependencies(&ctx)
+	err = builder.Steps.InjectDependencies.Execute(&ctx)
 	assert.Nil(t, err)
-	err = sanitizeDependencies(&ctx)
+	err = builder.Steps.SanitizeDependencies.Execute(&ctx)
 	assert.Nil(t, err)
 
 	assert.Contains(t, ctx.Maven.Project.Dependencies, maven.Dependency{
@@ -319,62 +255,3 @@ func TestSanitizeDependencies(t *testing.T) {
 		Version:    "1.2.3",
 	})
 }
-
-func TestListPublishedImages(t *testing.T) {
-	catalog, err := test.DefaultCatalog()
-	assert.Nil(t, err)
-
-	c, err := test.NewFakeClient(
-		&v1alpha1.IntegrationKit{
-			TypeMeta: metav1.TypeMeta{
-				APIVersion: v1alpha1.SchemeGroupVersion.String(),
-				Kind:       v1alpha1.IntegrationKindKind,
-			},
-			ObjectMeta: metav1.ObjectMeta{
-				Namespace: "ns",
-				Name:      "my-kit-1",
-				Labels: map[string]string{
-					"camel.apache.org/kit.type": v1alpha1.IntegrationKitTypePlatform,
-				},
-			},
-			Status: v1alpha1.IntegrationKitStatus{
-				Phase:          v1alpha1.IntegrationKitPhaseError,
-				Image:          "image-1",
-				CamelVersion:   catalog.Version,
-				RuntimeVersion: catalog.RuntimeVersion,
-			},
-		},
-		&v1alpha1.IntegrationKit{
-			TypeMeta: metav1.TypeMeta{
-				APIVersion: v1alpha1.SchemeGroupVersion.String(),
-				Kind:       v1alpha1.IntegrationKindKind,
-			},
-			ObjectMeta: metav1.ObjectMeta{
-				Namespace: "ns",
-				Name:      "my-kit-2",
-				Labels: map[string]string{
-					"camel.apache.org/kit.type": v1alpha1.IntegrationKitTypePlatform,
-				},
-			},
-			Status: v1alpha1.IntegrationKitStatus{
-				Phase:          v1alpha1.IntegrationKitPhaseReady,
-				Image:          "image-2",
-				CamelVersion:   catalog.Version,
-				RuntimeVersion: catalog.RuntimeVersion,
-			},
-		},
-	)
-
-	assert.Nil(t, err)
-	assert.NotNil(t, c)
-
-	i, err := listPublishedImages(&Context{
-		Client:  c,
-		Catalog: catalog,
-		C:       cancellable.NewContext(),
-	})
-
-	assert.Nil(t, err)
-	assert.Len(t, i, 1)
-	assert.Equal(t, "image-2", i[0].Image)
-}
diff --git a/pkg/builder/runtime/quarkus.go b/pkg/builder/runtime/quarkus.go
new file mode 100644
index 0000000..ddca59e
--- /dev/null
+++ b/pkg/builder/runtime/quarkus.go
@@ -0,0 +1,142 @@
+package runtime
+
+import (
+	"bufio"
+	"bytes"
+	"os"
+	"path"
+
+	"github.com/pkg/errors"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/builder"
+	"github.com/apache/camel-k/pkg/util/camel"
+	"github.com/apache/camel-k/pkg/util/defaults"
+	"github.com/apache/camel-k/pkg/util/maven"
+)
+
+// QuarkusSteps --
+var QuarkusSteps = []builder.Step{
+	Steps.GenerateQuarkusProject,
+	Steps.ComputeQuarkusDependencies,
+}
+
+func generateQuarkusProject(ctx *builder.Context) error {
+	// Catalog
+	if ctx.Catalog == nil {
+		c, err := camel.LoadCatalog(ctx.C, ctx.Client, ctx.Namespace, ctx.Build.Platform.Build.CamelVersion, ctx.Build.Platform.Build.RuntimeVersion)
+		if err != nil {
+			return err
+		}
+
+		ctx.Catalog = c
+	}
+
+	p := maven.NewProjectWithGAV("org.apache.camel.k.integration", "camel-k-integration", defaults.Version)
+	p.Properties = ctx.Build.Platform.Build.Properties
+	p.DependencyManagement = &maven.DependencyManagement{Dependencies: make([]maven.Dependency, 0)}
+	p.Dependencies = make([]maven.Dependency, 0)
+	p.Build = &maven.Build{Plugins: make([]maven.Plugin, 0)}
+
+	// DependencyManagement
+	p.DependencyManagement.Dependencies = append(p.DependencyManagement.Dependencies,
+		maven.Dependency{
+			GroupID:    "org.apache.camel.quarkus",
+			ArtifactID: "camel-quarkus-bom",
+			Version:    "0.2.0",
+			//Version:    ctx.Catalog.Version,
+			Type:  "pom",
+			Scope: "import",
+		},
+		maven.Dependency{
+			GroupID:    "org.apache.camel.k",
+			ArtifactID: "camel-k-runtime-bom",
+			Version:    ctx.Catalog.RuntimeVersion,
+			Type:       "pom",
+			Scope:      "import",
+		},
+	)
+
+	// Plugins
+	p.Build.Plugins = append(p.Build.Plugins,
+		maven.Plugin{
+			GroupID:    "io.quarkus",
+			ArtifactID: "quarkus-bootstrap-maven-plugin",
+			// TODO: must be the same as the version required by camel-k-runtime
+			Version: "0.21.2",
+		},
+		maven.Plugin{
+			GroupID:    "io.quarkus",
+			ArtifactID: "quarkus-maven-plugin",
+			// TODO: must be the same as the version required by camel-k-runtime
+			Version: "0.21.2",
+			Executions: []maven.Execution{
+				{
+					Goals: []string{
+						"build",
+					},
+				},
+			},
+		},
+	)
+
+	ctx.Maven.Project = p
+
+	return nil
+}
+
+func computeQuarkusDependencies(ctx *builder.Context) error {
+	mc := maven.NewContext(path.Join(ctx.Path, "maven"), ctx.Maven.Project)
+	mc.SettingsContent = ctx.Maven.SettingsData
+	mc.LocalRepository = ctx.Build.Platform.Build.LocalRepository
+	mc.Timeout = ctx.Build.Platform.Build.Maven.Timeout.Duration
+
+	// Build the project, as the quarkus-bootstrap plugin build-tree goal
+	// requires the artifact to be installed
+	mc.AddArgument("package")
+	if err := maven.Run(mc); err != nil {
+		return errors.Wrap(err, "failure while building project")
+	}
+
+	// Call the Quarkus dependencies plugin
+	mc.AdditionalArguments = nil
+	mc.AddArguments("quarkus-bootstrap:build-tree")
+	output := new(bytes.Buffer)
+	mc.Stdout = output
+	if err := maven.Run(mc); err != nil {
+		return errors.Wrap(err, "failure while determining dependencies")
+	}
+
+	scanner := bufio.NewScanner(output)
+	scanner.Split(bufio.ScanLines)
+	for scanner.Scan() {
+		gav, err := maven.ParseGAV(scanner.Text())
+		if err != nil {
+			continue
+		}
+
+		fileName := gav.GroupID + "." + gav.ArtifactID + "-" + gav.Version + "." + gav.Type
+		location := path.Join(mc.Path, "target", "lib", fileName)
+		_, err = os.Stat(location)
+		// We check that the dependency actually exists in the lib directory as the
+		// quarkus-bootstrap Maven plugin reports deployment dependencies as well
+		if os.IsNotExist(err) {
+			continue
+		}
+
+		ctx.Artifacts = append(ctx.Artifacts, v1alpha1.Artifact{
+			ID:       fileName,
+			Location: location,
+			Target:   path.Join("lib", fileName),
+		})
+	}
+
+	runner := "camel-k-integration-" + defaults.Version + "-runner.jar"
+	ctx.Artifacts = append(ctx.Artifacts, v1alpha1.Artifact{
+		ID:       runner,
+		Location: path.Join(mc.Path, "target", runner),
+		Target:   runner,
+	})
+
+	return nil
+}
diff --git a/pkg/builder/kaniko/kaniko.go b/pkg/builder/runtime/runtime.go
similarity index 58%
copy from pkg/builder/kaniko/kaniko.go
copy to pkg/builder/runtime/runtime.go
index f5e53cb..22106e0 100644
--- a/pkg/builder/kaniko/kaniko.go
+++ b/pkg/builder/runtime/runtime.go
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package kaniko
+package runtime
 
 import (
 	"github.com/apache/camel-k/pkg/builder"
@@ -25,28 +25,33 @@ func init() {
 	builder.RegisterSteps(Steps)
 }
 
+// TODO: organise runtime steps into nested structs
 type steps struct {
-	Publisher builder.Step
+	// Main
+	GenerateProject     builder.Step
+	ComputeDependencies builder.Step
+	// Quarkus
+	GenerateQuarkusProject     builder.Step
+	ComputeQuarkusDependencies builder.Step
 }
 
-// Steps --
 var Steps = steps{
-	Publisher: builder.NewStep(
-		builder.ApplicationPublishPhase,
-		publisher,
+	// Main
+	GenerateProject: builder.NewStep(
+		builder.ProjectGenerationPhase,
+		generateProject,
+	),
+	ComputeDependencies: builder.NewStep(
+		builder.ProjectBuildPhase,
+		computeDependencies,
+	),
+	// Quarkus
+	GenerateQuarkusProject: builder.NewStep(
+		builder.ProjectGenerationPhase,
+		generateQuarkusProject,
+	),
+	ComputeQuarkusDependencies: builder.NewStep(
+		builder.ProjectBuildPhase,
+		computeQuarkusDependencies,
 	),
 }
-
-// DefaultSteps --
-var DefaultSteps = []builder.Step{
-	builder.Steps.GenerateProject,
-	builder.Steps.GenerateProjectSettings,
-	builder.Steps.InjectDependencies,
-	builder.Steps.SanitizeDependencies,
-	builder.Steps.ComputeDependencies,
-	builder.Steps.IncrementalPackager,
-	Steps.Publisher,
-}
-
-// BuildDir is the directory where to build artifacts (shared with the Kaniko pod)
-var BuildDir = "/workspace"
diff --git a/pkg/builder/s2i/s2i.go b/pkg/builder/s2i/s2i.go
index b1a3bd8..8ccb13e 100644
--- a/pkg/builder/s2i/s2i.go
+++ b/pkg/builder/s2i/s2i.go
@@ -37,13 +37,7 @@ var Steps = steps{
 	),
 }
 
-// DefaultSteps --
-var DefaultSteps = []builder.Step{
-	builder.Steps.GenerateProject,
-	builder.Steps.GenerateProjectSettings,
-	builder.Steps.InjectDependencies,
-	builder.Steps.SanitizeDependencies,
-	builder.Steps.ComputeDependencies,
-	builder.Steps.IncrementalPackager,
+// S2iSteps --
+var S2iSteps = []builder.Step{
 	Steps.Publisher,
 }
diff --git a/pkg/trait/builder.go b/pkg/trait/builder.go
index 7b167ff..a017cc2 100644
--- a/pkg/trait/builder.go
+++ b/pkg/trait/builder.go
@@ -19,7 +19,9 @@ package trait
 
 import (
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/builder"
 	"github.com/apache/camel-k/pkg/builder/kaniko"
+	"github.com/apache/camel-k/pkg/builder/runtime"
 	"github.com/apache/camel-k/pkg/builder/s2i"
 	"github.com/apache/camel-k/pkg/platform"
 )
@@ -44,12 +46,23 @@ func (t *builderTrait) Configure(e *Environment) (bool, error) {
 }
 
 func (t *builderTrait) Apply(e *Environment) error {
+	e.Steps = append(e.Steps, builder.DefaultSteps...)
 	if platform.SupportsS2iPublishStrategy(e.Platform) {
-		e.Steps = s2i.DefaultSteps
+		e.Steps = append(e.Steps, s2i.S2iSteps...)
 	} else if platform.SupportsKanikoPublishStrategy(e.Platform) {
-		e.Steps = kaniko.DefaultSteps
+		e.Steps = append(e.Steps, kaniko.KanikoSteps...)
 		e.BuildDir = kaniko.BuildDir
 	}
 
+	quarkus := e.Catalog.GetTrait("quarkus").(*quarkusTrait)
+
+	if quarkus.isEnabled() {
+		// Add build steps for Quarkus runtime
+		quarkus.addBuildSteps(e)
+	} else {
+		// Add build steps for default runtime
+		e.Steps = append(e.Steps, runtime.MainSteps...)
+	}
+
 	return nil
 }
diff --git a/pkg/trait/dependencies.go b/pkg/trait/dependencies.go
index 9659577..69fb824 100644
--- a/pkg/trait/dependencies.go
+++ b/pkg/trait/dependencies.go
@@ -51,41 +51,54 @@ func (t *dependenciesTrait) Apply(e *Environment) error {
 			util.StringSliceUniqueAdd(&dependencies, dep)
 		}
 	}
+
+	quarkus := e.Catalog.GetTrait("quarkus").(*quarkusTrait)
+	if quarkus.isEnabled() {
+		err := quarkus.addRuntimeDependencies(e, &dependencies)
+		if err != nil {
+			return err
+		}
+	} else {
+		addDefaultRuntimeDependencies(e, &dependencies)
+	}
+
+	// sort the dependencies to get always the same list if they don't change
+	sort.Strings(dependencies)
+	e.Integration.Status.Dependencies = dependencies
+	return nil
+}
+
+func addDefaultRuntimeDependencies(e *Environment, dependencies *[]string) {
 	for _, s := range e.Integration.Sources() {
 		meta := metadata.Extract(e.CamelCatalog, s)
 
 		switch s.InferLanguage() {
 		case v1alpha1.LanguageGroovy:
-			util.StringSliceUniqueAdd(&dependencies, "mvn:org.apache.camel.k/camel-k-loader-groovy")
+			util.StringSliceUniqueAdd(dependencies, "mvn:org.apache.camel.k/camel-k-loader-groovy")
 		case v1alpha1.LanguageKotlin:
-			util.StringSliceUniqueAdd(&dependencies, "mvn:org.apache.camel.k/camel-k-loader-kotlin")
+			util.StringSliceUniqueAdd(dependencies, "mvn:org.apache.camel.k/camel-k-loader-kotlin")
 		case v1alpha1.LanguageYaml:
-			util.StringSliceUniqueAdd(&dependencies, "mvn:org.apache.camel.k/camel-k-loader-yaml")
+			util.StringSliceUniqueAdd(dependencies, "mvn:org.apache.camel.k/camel-k-loader-yaml")
 		case v1alpha1.LanguageXML:
-			util.StringSliceUniqueAdd(&dependencies, "mvn:org.apache.camel.k/camel-k-loader-xml")
+			util.StringSliceUniqueAdd(dependencies, "mvn:org.apache.camel.k/camel-k-loader-xml")
 		case v1alpha1.LanguageJavaScript:
-			util.StringSliceUniqueAdd(&dependencies, "mvn:org.apache.camel.k/camel-k-loader-js")
+			util.StringSliceUniqueAdd(dependencies, "mvn:org.apache.camel.k/camel-k-loader-js")
 		case v1alpha1.LanguageJavaClass:
-			util.StringSliceUniqueAdd(&dependencies, "mvn:org.apache.camel.k/camel-k-loader-java")
+			util.StringSliceUniqueAdd(dependencies, "mvn:org.apache.camel.k/camel-k-loader-java")
 		case v1alpha1.LanguageJavaSource:
-			util.StringSliceUniqueAdd(&dependencies, "mvn:org.apache.camel.k/camel-k-loader-java")
+			util.StringSliceUniqueAdd(dependencies, "mvn:org.apache.camel.k/camel-k-loader-java")
 		}
 
 		if strings.HasPrefix(s.Loader, "knative-source") {
-			util.StringSliceUniqueAdd(&dependencies, "mvn:org.apache.camel.k/camel-k-loader-knative")
-			util.StringSliceUniqueAdd(&dependencies, "mvn:org.apache.camel.k/camel-k-runtime-knative")
+			util.StringSliceUniqueAdd(dependencies, "mvn:org.apache.camel.k/camel-k-loader-knative")
+			util.StringSliceUniqueAdd(dependencies, "mvn:org.apache.camel.k/camel-k-runtime-knative")
 		}
 
 		// main required by default
-		util.StringSliceUniqueAdd(&dependencies, "mvn:org.apache.camel.k/camel-k-runtime-main")
+		util.StringSliceUniqueAdd(dependencies, "mvn:org.apache.camel.k/camel-k-runtime-main")
 
 		for _, d := range meta.Dependencies.List() {
-			util.StringSliceUniqueAdd(&dependencies, d)
+			util.StringSliceUniqueAdd(dependencies, d)
 		}
 	}
-
-	// sort the dependencies to get always the same list if they don't change
-	sort.Strings(dependencies)
-	e.Integration.Status.Dependencies = dependencies
-	return nil
 }
diff --git a/pkg/trait/dependencies_test.go b/pkg/trait/dependencies_test.go
index fed00c9..8e75159 100644
--- a/pkg/trait/dependencies_test.go
+++ b/pkg/trait/dependencies_test.go
@@ -27,6 +27,7 @@ import (
 
 func TestDependenciesTraitApplicability(t *testing.T) {
 	e := &Environment{
+		Catalog:     NewEnvironmentTestCatalog(),
 		Integration: &v1alpha1.Integration{},
 	}
 
@@ -51,6 +52,7 @@ func TestIntegrationDefaultDeps(t *testing.T) {
 	assert.Nil(t, err)
 
 	e := &Environment{
+		Catalog:      NewEnvironmentTestCatalog(),
 		CamelCatalog: catalog,
 		Integration: &v1alpha1.Integration{
 			Spec: v1alpha1.IntegrationSpec{
@@ -93,6 +95,7 @@ func TestIntegrationCustomDeps(t *testing.T) {
 	assert.Nil(t, err)
 
 	e := &Environment{
+		Catalog:      NewEnvironmentTestCatalog(),
 		CamelCatalog: catalog,
 		Integration: &v1alpha1.Integration{
 			Spec: v1alpha1.IntegrationSpec{
@@ -140,6 +143,7 @@ func TestIntegrationAutoGeneratedDeps(t *testing.T) {
 	assert.Nil(t, err)
 
 	e := &Environment{
+		Catalog:      NewEnvironmentTestCatalog(),
 		CamelCatalog: catalog,
 		Integration: &v1alpha1.Integration{
 			Spec: v1alpha1.IntegrationSpec{
@@ -193,6 +197,7 @@ func TestIntegrationCustomLoader(t *testing.T) {
 	assert.Nil(t, err)
 
 	e := &Environment{
+		Catalog:      NewEnvironmentTestCatalog(),
 		CamelCatalog: catalog,
 		Integration: &v1alpha1.Integration{
 			Spec: v1alpha1.IntegrationSpec{
diff --git a/pkg/trait/environment.go b/pkg/trait/environment.go
index c282e34..fb73bcf 100644
--- a/pkg/trait/environment.go
+++ b/pkg/trait/environment.go
@@ -35,6 +35,7 @@ const (
 	envVarCamelKRuntimeVersion = "CAMEL_K_RUNTIME_VERSION"
 	envVarCamelVersion         = "CAMEL_VERSION"
 	envVarMainClass            = "JAVA_MAIN_CLASS"
+	envVarAppJAR               = "JAVA_APP_JAR"
 	defaultMainClass           = "org.apache.camel.k.main.Application"
 )
 
@@ -63,7 +64,12 @@ func (t *environmentTrait) Apply(e *Environment) error {
 		envvar.SetValFrom(&e.EnvVars, envVarPodName, "metadata.name")
 	}
 
-	envvar.SetVal(&e.EnvVars, envVarMainClass, defaultMainClass)
+	quarkus := e.Catalog.GetTrait("quarkus").(*quarkusTrait)
+	if quarkus.isEnabled() {
+		quarkus.addContainerEnvironment(e)
+	} else {
+		envvar.SetVal(&e.EnvVars, envVarMainClass, defaultMainClass)
+	}
 
 	return nil
 }
diff --git a/pkg/trait/quarkus.go b/pkg/trait/quarkus.go
new file mode 100644
index 0000000..8b70b11
--- /dev/null
+++ b/pkg/trait/quarkus.go
@@ -0,0 +1,94 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package trait
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/builder/runtime"
+	"github.com/apache/camel-k/pkg/metadata"
+	"github.com/apache/camel-k/pkg/util"
+	"github.com/apache/camel-k/pkg/util/defaults"
+	"github.com/apache/camel-k/pkg/util/envvar"
+)
+
+type quarkusTrait struct {
+	BaseTrait `property:",squash"`
+}
+
+func newQuarkusTrait() *quarkusTrait {
+	return &quarkusTrait{
+		BaseTrait: newBaseTrait("quarkus"),
+	}
+}
+
+func (t *quarkusTrait) isEnabled() bool {
+	return t.Enabled != nil && *t.Enabled
+}
+
+func (t *quarkusTrait) Configure(e *Environment) (bool, error) {
+	return t.isEnabled(), nil
+}
+
+func (t *quarkusTrait) Apply(e *Environment) error {
+	return nil
+}
+
+func (t *quarkusTrait) addBuildSteps(e *Environment) {
+	e.Steps = append(e.Steps, runtime.QuarkusSteps...)
+}
+
+func (t *quarkusTrait) addRuntimeDependencies(e *Environment, dependencies *[]string) error {
+	for _, s := range e.Integration.Sources() {
+		meta := metadata.Extract(e.CamelCatalog, s)
+
+		switch language := s.InferLanguage(); language {
+		case v1alpha1.LanguageYaml:
+			addRuntimeDependency("camel-k-quarkus-loader-yaml", dependencies)
+		case v1alpha1.LanguageXML:
+			addRuntimeDependency("camel-k-quarkus-loader-xml", dependencies)
+		case v1alpha1.LanguageJavaScript:
+			addRuntimeDependency("camel-k-quarkus-loader-js", dependencies)
+		default:
+			return fmt.Errorf("unsupported language for Quarkus runtime: %s", language)
+		}
+
+		if strings.HasPrefix(s.Loader, "knative-source") {
+			addRuntimeDependency("camel-k-quarkus-loader-knative", dependencies)
+			addRuntimeDependency("camel-k-quarkus-knative", dependencies)
+		}
+
+		// main required by default
+		addRuntimeDependency("camel-k-runtime-quarkus", dependencies)
+
+		for _, d := range meta.Dependencies.List() {
+			util.StringSliceUniqueAdd(dependencies, d)
+		}
+	}
+	return nil
+}
+
+func (t *quarkusTrait) addContainerEnvironment(e *Environment) {
+	envvar.SetVal(&e.EnvVars, envVarAppJAR, "camel-k-integration-"+defaults.Version+"-runner.jar")
+}
+
+func addRuntimeDependency(dependency string, dependencies *[]string) {
+	util.StringSliceUniqueAdd(dependencies, fmt.Sprintf("mvn:org.apache.camel.k/%s", dependency))
+}
diff --git a/pkg/trait/rest-dsl.go b/pkg/trait/rest-dsl.go
index ef6b22b..6a03ad4 100644
--- a/pkg/trait/rest-dsl.go
+++ b/pkg/trait/rest-dsl.go
@@ -27,15 +27,13 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/apache/camel-k/pkg/util/kubernetes"
-
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
-	"github.com/apache/camel-k/pkg/gzip"
-
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/gzip"
 	"github.com/apache/camel-k/pkg/util/defaults"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"github.com/apache/camel-k/pkg/util/maven"
 )
 
diff --git a/pkg/trait/trait_catalog.go b/pkg/trait/trait_catalog.go
index b682314..96b6862 100644
--- a/pkg/trait/trait_catalog.go
+++ b/pkg/trait/trait_catalog.go
@@ -52,6 +52,7 @@ type Catalog struct {
 	tClasspath        Trait
 	tRestDsl          Trait
 	tProbes           Trait
+	tQuarkus          Trait
 	tContainer        Trait
 }
 
@@ -80,6 +81,7 @@ func NewCatalog(ctx context.Context, c client.Client) *Catalog {
 		tEnvironment:      newEnvironmentTrait(),
 		tClasspath:        newClasspathTrait(),
 		tProbes:           newProbesTrait(),
+		tQuarkus:          newQuarkusTrait(),
 		tContainer:        newContainerTrait(),
 	}
 
@@ -117,6 +119,7 @@ func (c *Catalog) allTraits() []Trait {
 		c.tEnvironment,
 		c.tClasspath,
 		c.tProbes,
+		c.tQuarkus,
 		c.tContainer,
 	}
 }
@@ -133,6 +136,7 @@ func (c *Catalog) traitsFor(environment *Environment) []Trait {
 			c.tRestDsl,
 			c.tDependencies,
 			c.tBuilder,
+			c.tQuarkus,
 			c.tEnvironment,
 			c.tDeployer,
 			c.tDeployment,
@@ -155,6 +159,7 @@ func (c *Catalog) traitsFor(environment *Environment) []Trait {
 			c.tRestDsl,
 			c.tDependencies,
 			c.tBuilder,
+			c.tQuarkus,
 			c.tEnvironment,
 			c.tDeployer,
 			c.tDeployment,
@@ -178,6 +183,7 @@ func (c *Catalog) traitsFor(environment *Environment) []Trait {
 			c.tKnative,
 			c.tDependencies,
 			c.tBuilder,
+			c.tQuarkus,
 			c.tEnvironment,
 			c.tDeployer,
 			c.tDeployment,
diff --git a/pkg/util/maven/maven.go b/pkg/util/maven/maven.go
index a881bd4..067feca 100644
--- a/pkg/util/maven/maven.go
+++ b/pkg/util/maven/maven.go
@@ -90,7 +90,6 @@ func Run(ctx Context) error {
 	}
 
 	args := make([]string, 0)
-	args = append(args, ctx.AdditionalArguments...)
 	args = append(args, "--batch-mode")
 
 	if ctx.LocalRepository == "" {
@@ -109,6 +108,8 @@ func Run(ctx Context) error {
 		args = append(args, "--settings", settingsPath)
 	}
 
+	args = append(args, ctx.AdditionalArguments...)
+
 	timeout := ctx.Timeout
 	if timeout == 0 {
 		timeout = math.MaxInt64
@@ -120,7 +121,11 @@ func Run(ctx Context) error {
 	cmd := exec.CommandContext(c, mvnCmd, args...)
 	cmd.Dir = ctx.Path
 	cmd.Stderr = os.Stderr
-	cmd.Stdout = os.Stdout
+	if ctx.Stdout != nil {
+		cmd.Stdout = ctx.Stdout
+	} else {
+		cmd.Stdout = os.Stdout
+	}
 
 	Log.WithValues("timeout", timeout.String()).Infof("executing: %s", strings.Join(cmd.Args, " "))
 
@@ -139,8 +144,6 @@ func ParseGAV(gav string) (Dependency, error) {
 	rex := regexp.MustCompile("([^: ]+):([^: ]+)(:([^: ]*)(:([^: ]+))?)?(:([^: ]+))?")
 	res := rex.FindStringSubmatch(gav)
 
-	fmt.Println(res, len(res))
-
 	if res == nil || len(res) < 9 {
 		return Dependency{}, errors.New("GAV must match <groupId>:<artifactId>[:<packagingType>[:<classifier>]]:(<version>|'?')")
 	}
diff --git a/pkg/util/maven/maven_types.go b/pkg/util/maven/maven_types.go
index 6adbd06..0bd31f4 100644
--- a/pkg/util/maven/maven_types.go
+++ b/pkg/util/maven/maven_types.go
@@ -21,6 +21,7 @@ import (
 	"bytes"
 	"encoding/xml"
 	"fmt"
+	"io"
 	"time"
 )
 
@@ -109,6 +110,7 @@ type Context struct {
 	AdditionalEntries   map[string]interface{}
 	Timeout             time.Duration
 	LocalRepository     string
+	Stdout              io.Writer
 }
 
 // AddEntry --