Repository: kubevela/kubevela

Issue:
KubeVela dependsOn ignores failed component status and deploys dependent components anyway
KubeVela dependsOn ignores failed component status and deploys dependent components anyway

**To Reproduce**
 
Steps to reproduce the behaviour:
1. The YAML file of Application I applied.
```
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: dependencytest
  namespace: default
spec:
  components:
    - name: express-server
      type: webservice
      properties: {} # Intentionally not setting mandatory image to make this fail
    - name: worker-service
      type: webservice
      dependsOn:
        - express-server
      properties:
        image: nginx:1.20

```
2. Wait 2-3 minutes for retries to complete and the express-server component status to become failed
3. Check the status of the application  `vela status dependencytest`
Workflow:
```
 mode: DAG-DAG
  finished: true
  Suspend: false
  Terminated: true
  Steps
  - id: zbbxxk79qg
    name: express-server
    type: apply-component
    phase: failed
    message: function call error for : GenerateComponentManifest: evaluate base template component=express-server app=dependencytest: failed to have the workload/trait unstructured: output.spec.template.spec.containers.0.image: incomplete value string (value: cue/format: unsupported node type <nil>)
  - id: tv4848wbnc
    name: worker-service
    type: apply-component
    phase: succeeded  # ❌ This should NOT succeed while dependency is failed
```
 
**Expected behaviour** Components with dependsOn should wait until their dependencies are successfully running. 
 
**Actual**: Components with dependsOn deploy regardless of dependency failure status
**Impact**: Breaks dependency orchestration and can lead to runtime failures in dependent services.

**KubeVela Version** 1.10.x


Hints from issue comments:
@oanasc: Note using the workflow steps with dependsOn works correctly. The problem is we want to avoid users having to setup the very verbose workflow steps and use the dependsOn in the component
```
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: dependencytest
  namespace: default
spec:
  components:
    - name: express-server
      type: webservice
      properties:
        noimage: "tres"
        #image: oamdev/hello-world:invalidtag
    - name: worker-service
      type: webservice
      dependsOn:
        - express-server
      properties:
        image: nginx:1.20
  workflow:
    steps:
      - name: apply-es
        type: apply-component
        properties:
          component: express-server
      - name: apply-ws
        type: apply-component
        properties:
          component: worker-service
        dependsOn:
          - apply-es
```

Solution patch:
diff --git a/.github/workflows/back-port.yml b/.github/workflows/back-port.yml
index 6233acfb..f0a0b58a 100644
--- a/.github/workflows/back-port.yml
+++ b/.github/workflows/back-port.yml
@@ -17,7 +17,7 @@ jobs:
       pull-requests: write
     steps:
       - name: Checkout
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
         with:
           fetch-depth: 0
 
diff --git a/.github/workflows/chart.yml b/.github/workflows/chart.yml
index 47ffd575..bd85614d 100644
--- a/.github/workflows/chart.yml
+++ b/.github/workflows/chart.yml
@@ -17,7 +17,7 @@ jobs:
       HELM_CHART_NAME: vela-core
     runs-on: ubuntu-22.04
     steps:
-      - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
       - name: Get git revision
         id: vars
         shell: bash
@@ -28,7 +28,7 @@ jobs:
         with:
           version: v3.4.0
       - name: Setup node
-        uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b
+        uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
         with:
           node-version: '14'
       - name: Generate helm doc
diff --git a/.github/workflows/definition-lint.yml b/.github/workflows/definition-lint.yml
index f8e46a34..1714f5c3 100644
--- a/.github/workflows/definition-lint.yml
+++ b/.github/workflows/definition-lint.yml
@@ -23,19 +23,19 @@ jobs:
     runs-on: ubuntu-22.04
     steps:
       - name: Setup Go
-        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5
         with:
           go-version: ${{ env.GO_VERSION }}
 
       - name: Checkout
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
         with:
           submodules: true
 
       - name: Setup KinD
         run: |
-          go install sigs.k8s.io/kind@v0.19.0
-          kind create cluster
+          go install sigs.k8s.io/kind@v0.29.0
+          kind create cluster --image=kindest/node:v1.31.9
 
       - name: Definition Doc generate check
         run: |
diff --git a/.github/workflows/e2e-multicluster-test.yml b/.github/workflows/e2e-multicluster-test.yml
index d04e4556..b2be990c 100644
--- a/.github/workflows/e2e-multicluster-test.yml
+++ b/.github/workflows/e2e-multicluster-test.yml
@@ -51,7 +51,7 @@ jobs:
 
     steps:
       - name: Check out code into the Go module directory
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
 
       - name: Install tools
         run: |
@@ -61,7 +61,7 @@ jobs:
           sudo snap install helm --classic
 
       - name: Setup Go
-        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5
         with:
           go-version: ${{ env.GO_VERSION }}
 
@@ -71,12 +71,12 @@ jobs:
 
       - name: Setup KinD
         run: |
-          go install sigs.k8s.io/kind@v0.24.0
+          go install sigs.k8s.io/kind@v0.29.0
           kind delete cluster --name worker || true
-          kind create cluster --name worker --image=kindest/node:v1.31.1
+          kind create cluster --name worker --image=kindest/node:v1.31.9
           kind export kubeconfig --internal --name worker --kubeconfig /tmp/worker.kubeconfig
           kind delete cluster || true
-          kind create cluster --image=kindest/node:v1.31.1
+          kind create cluster --image=kindest/node:v1.31.9
 
       - name: Load image
         run: |
@@ -99,7 +99,7 @@ jobs:
           make end-e2e-core-shards
 
       - name: Upload coverage report
-        uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d
+        uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
           files: /tmp/e2e-profile.out,/tmp/e2e_multicluster_test.out
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index e9b4b148..de063b15 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -51,7 +51,7 @@ jobs:
 
     steps:
       - name: Check out code into the Go module directory
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
 
       - name: Install tools
         run: |
@@ -61,7 +61,7 @@ jobs:
           sudo snap install helm --classic
 
       - name: Setup Go
-        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5
         with:
           go-version: ${{ env.GO_VERSION }}
 
@@ -71,9 +71,9 @@ jobs:
 
       - name: Setup KinD
         run: |
-          go install sigs.k8s.io/kind@v0.24.0
+          go install sigs.k8s.io/kind@v0.29.0
           kind delete cluster || true
-          kind create cluster --image=kindest/node:v1.29.8
+          kind create cluster --image=kindest/node:v1.31.9
 
       - name: Get Ginkgo
         run: |
@@ -106,7 +106,7 @@ jobs:
         run: make end-e2e
 
       - name: Upload coverage report
-        uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d
+        uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
           files: /tmp/e2e-profile.out
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 8495f6ea..1de8a4aa 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -43,12 +43,12 @@ jobs:
 
     steps:
       - name: Setup Go
-        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5
         with:
           go-version: ${{ env.GO_VERSION }}
 
       - name: Checkout
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
         with:
           submodules: true
 
@@ -68,12 +68,12 @@ jobs:
 
     steps:
       - name: Setup Go
-        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5
         with:
           go-version: ${{ env.GO_VERSION }}
 
       - name: Checkout
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
         with:
           submodules: true
 
@@ -93,17 +93,17 @@ jobs:
 
     steps:
       - name: Checkout
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
         with:
           submodules: true
 
       - name: Setup Go
-        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5
         with:
           go-version: ${{ env.GO_VERSION }}
 
       - name: Setup node
-        uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b
+        uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
         with:
           node-version: "14"
 
@@ -116,9 +116,9 @@ jobs:
 
       - name: Setup KinD
         run: |
-          go install sigs.k8s.io/kind@v0.19.0
+          go install sigs.k8s.io/kind@v0.29.0
           kind delete cluster --name kind || true
-          kind create cluster --name kind --image=kindest/node:v1.26.4 --kubeconfig ~/.kube/config
+          kind create cluster --name kind --image=kindest/node:v1.31.9 --kubeconfig ~/.kube/config
 
       - name: Run cross-build
         run: make cross-build
@@ -138,12 +138,12 @@ jobs:
 
     steps:
       - name: Checkout
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
         with:
           submodules: true
 
       - name: Setup Go
-        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5
         with:
           go-version: ${{ env.GO_VERSION }}
 
@@ -169,15 +169,15 @@ jobs:
     if: needs.detect-noop.outputs.noop != 'true'
     steps:
       - name: Checkout
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
         with:
           submodules: true
       - name: Set up QEMU
-        uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
+        uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392
       - name: Set up Docker Buildx
-        uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0
+        uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435
       - name: Build Test for vela core
-        uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
+        uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
         with:
           context: .
           file: Dockerfile
@@ -189,15 +189,15 @@ jobs:
     if: needs.detect-noop.outputs.noop != 'true'
     steps:
       - name: Checkout
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
         with:
           submodules: true
       - name: Set up QEMU
-        uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
+        uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392
       - name: Set up Docker Buildx
-        uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0
-      - name: Build Test for CLI
-        uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
+        uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435
+      - name: Build Test for CLI 
+        uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
         with:
           context: .
           file: Dockerfile.cli
\ No newline at end of file
diff --git a/.github/workflows/sdk-test.yml b/.github/workflows/sdk-test.yml
index 64ef7986..02cbd632 100644
--- a/.github/workflows/sdk-test.yml
+++ b/.github/workflows/sdk-test.yml
@@ -26,10 +26,10 @@ jobs:
     runs-on: ubuntu-22.04
     steps:
       - name: Check out code into the Go module directory
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
 
       - name: Setup Go
-        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5
         with:
           go-version: ${{ env.GO_VERSION }}
 
@@ -40,8 +40,8 @@ jobs:
 
       - name: Setup KinD
         run: |
-          go install sigs.k8s.io/kind@v0.19.0
-          kind create cluster
+          go install sigs.k8s.io/kind@v0.29.0
+          kind create cluster --image=kindest/node:v1.31.9
 
       - name: Build CLI
         run: make vela-cli
diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml
index 837e1503..ed78a19b 100644
--- a/.github/workflows/unit-test.yml
+++ b/.github/workflows/unit-test.yml
@@ -42,12 +42,12 @@ jobs:
 
     steps:
       - name: Set up Go
-        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5
         with:
           go-version: ${{ env.GO_VERSION }}
 
       - name: Check out code into the Go module directory
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
         with:
           submodules: true
 
@@ -66,16 +66,16 @@ jobs:
 
       - name: Setup KinD
         run: |
-          go install sigs.k8s.io/kind@v0.19.0
-          kind create cluster
+          go install sigs.k8s.io/kind@v0.29.0
+          kind create cluster --image=kindest/node:v1.31.9
 
       - name: Run Make test
         run: make test
 
       - name: Upload coverage report
-        uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d
+        uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 #v5.4.3
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
-          file: ./coverage.txt
+          files: ./coverage.txt
           flags: core-unittests
           name: codecov-umbrella
diff --git a/README.md b/README.md
index d209bbfd..40b89ca8 100644
--- a/README.md
+++ b/README.md
@@ -115,4 +115,4 @@ Security is a first priority thing for us at KubeVela. If you come across a rela
 
 ## Code of Conduct
 
-KubeVela adopts [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
+KubeVela adopts [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
\ No newline at end of file
diff --git a/e2e/addon/mock/testrepo/helm-repo/index.yaml b/e2e/addon/mock/testrepo/helm-repo/index.yaml
index 78946b3a..fc089d7d 100644
--- a/e2e/addon/mock/testrepo/helm-repo/index.yaml
+++ b/e2e/addon/mock/testrepo/helm-repo/index.yaml
@@ -22,7 +22,7 @@ entries:
       version: 2.0.0
       annotations:
         system.vela: ">=1.5.0"
-        system.kubernetes: ">=1.30.0"
+        system.kubernetes: ">=1.32.0"
   vela-workflow:
     - annotations:
         system.vela: '>=v1.6.0-beta.1'
diff --git a/pkg/definition/ast/transformer.go b/pkg/definition/ast/transformer.go
index a6ef3af6..987b022e 100644
--- a/pkg/definition/ast/transformer.go
+++ b/pkg/definition/ast/transformer.go
@@ -27,14 +27,22 @@ import (
 
 const (
 	// status is the path to the status field in the metadata
-	status = "attributes.status.details"
+	status       = "attributes.status.details"
+	healthPolicy = "attributes.status.healthPolicy"
+	customStatus = "attributes.status.customStatus"
 	// localFieldPrefix is the prefix for local fields not output to the status
 	localFieldPrefix = "$"
 )
 
 // EncodeMetadata encodes native CUE in the metadata fields to a CUE string literal
 func EncodeMetadata(field *ast.Field) error {
-	if err := marshalStatusDetailsField(field); err != nil {
+	if err := marshalField[*ast.StructLit](field, healthPolicy, validateHealthPolicyField); err != nil {
+		return err
+	}
+	if err := marshalField[*ast.StructLit](field, customStatus, validateCustomStatusField); err != nil {
+		return err
+	}
+	if err := marshalField[*ast.StructLit](field, status, validateStatusField); err != nil {
 		return err
 	}
 	return nil
@@ -42,65 +50,75 @@ func EncodeMetadata(field *ast.Field) error {
 
 // DecodeMetadata decodes a CUE string literal in the metadata fields to native CUE expressions
 func DecodeMetadata(field *ast.Field) error {
-	if err := unmarshalStatusDetailsField(field); err != nil {
+	if err := unmarshalField[*ast.StructLit](field, healthPolicy, validateHealthPolicyField); err != nil {
+		return err
+	}
+	if err := unmarshalField[*ast.StructLit](field, customStatus, validateCustomStatusField); err != nil {
+		return err
+	}
+	if err := unmarshalField[*ast.StructLit](field, status, validateStatusField); err != nil {
 		return err
 	}
 	return nil
 }
 
-func marshalStatusDetailsField(field *ast.Field) error {
-	if statusField, ok := GetFieldByPath(field, status); ok {
+func marshalField[T ast.Node](field *ast.Field, key string, validator func(T) error) error {
+	if statusField, ok := GetFieldByPath(field, key); ok {
 		switch expr := statusField.Value.(type) {
 		case *ast.BasicLit:
 			if expr.Kind != token.STRING {
-				return fmt.Errorf("expected status field to be string, got %v", expr.Kind)
+				return fmt.Errorf("expected %s field to be string, got %v", key, expr.Kind)
 			}
-			if err := ValidateCueStringLiteral[*ast.StructLit](expr, validateStatusField); err != nil {
-				return fmt.Errorf("status.details field failed validation: %w", err)
+			if err := ValidateCueStringLiteral[T](expr, validator); err != nil {
+				return fmt.Errorf("%s field failed validation: %w", key, err)
 			}
 			return nil
 
 		case *ast.StructLit:
-			v, _ := statusField.Value.(*ast.StructLit)
-			err := validateStatusField(v)
+			structLit := expr
+			v, ok := ast.Node(structLit).(T)
+			if !ok {
+				return fmt.Errorf("%s field: cannot convert *ast.StructLit to expected type", key)
+			}
+			err := validator(v)
 			if err != nil {
 				return err
 			}
-			strLit, err := StringifyStructLitAsCueString(v)
+			strLit, err := StringifyStructLitAsCueString(structLit)
 			if err != nil {
 				return err
 			}
-			UpdateNodeByPath(field, status, strLit)
+			UpdateNodeByPath(field, key, strLit)
 			return nil
 
 		default:
-			return fmt.Errorf("unexpected type for status field: %T", expr)
+			return fmt.Errorf("unexpected type for %s field: %T", key, expr)
 		}
 	}
 	return nil
 }
 
-func unmarshalStatusDetailsField(field *ast.Field) error {
-	if statusField, ok := GetFieldByPath(field, status); ok {
+func unmarshalField[T ast.Node](field *ast.Field, key string, validator func(T) error) error {
+	if statusField, ok := GetFieldByPath(field, key); ok {
 		basicLit, ok := statusField.Value.(*ast.BasicLit)
 		if !ok || basicLit.Kind != token.STRING {
-			return fmt.Errorf("status.details field is not a string literal")
+			return fmt.Errorf("%s field is not a string literal", key)
 		}
 
-		err := ValidateCueStringLiteral[*ast.StructLit](basicLit, validateStatusField)
+		err := ValidateCueStringLiteral[T](basicLit, validator)
 		if err != nil {
-			return fmt.Errorf("status field failed validation: %w", err)
+			return fmt.Errorf("%s field failed validation: %w", key, err)
 		}
 
 		unquoted := strings.TrimSpace(TrimCueRawString(basicLit.Value))
 		expr, err := parser.ParseExpr("-", WrapCueStruct(unquoted))
 		if err != nil {
-			return fmt.Errorf("unexpected error re-parsing validated string: %w", err)
+			return fmt.Errorf("unexpected error re-parsing validated %s string: %w", key, err)
 		}
 
 		structLit, ok := expr.(*ast.StructLit)
 		if !ok {
-			return fmt.Errorf("expected struct after validation")
+			return fmt.Errorf("expected struct after validation in field %s", key)
 		}
 
 		statusField.Value = structLit
@@ -134,3 +152,55 @@ func validateStatusField(sl *ast.StructLit) error {
 	}
 	return nil
 }
+
+func validateCustomStatusField(sl *ast.StructLit) error {
+	validator := func(expr ast.Expr) error {
+		switch v := expr.(type) {
+		case *ast.BasicLit:
+			if v.Kind != token.STRING {
+				return fmt.Errorf("customStatus field 'message' must be a string, got %v", v.Kind)
+			}
+		case *ast.Interpolation, *ast.CallExpr, *ast.SelectorExpr, *ast.Ident, *ast.BinaryExpr, *ast.ParenExpr,
+			*ast.ListLit, *ast.IndexExpr, *ast.SliceExpr, *ast.Comprehension:
+		default:
+			return fmt.Errorf("customStatus field 'message' must be a string expression, got %T", v)
+		}
+		return nil
+	}
+
+	found, err := FindAndValidateField(sl, "message", validator)
+	if err != nil {
+		return err
+	}
+	if !found {
+		return fmt.Errorf("customStatus must contain a 'message' field")
+	}
+
+	return nil
+}
+
+func validateHealthPolicyField(sl *ast.StructLit) error {
+	validator := func(expr ast.Expr) error {
+		switch v := expr.(type) {
+		case *ast.Ident:
+		case *ast.BasicLit:
+			if v.Kind != token.TRUE && v.Kind != token.FALSE {
+				return fmt.Errorf("healthPolicy field 'isHealth' must be a boolean literal (true/false), got %v", v.Kind)
+			}
+		case *ast.BinaryExpr, *ast.UnaryExpr, *ast.CallExpr, *ast.SelectorExpr, *ast.ParenExpr:
+		default:
+			return fmt.Errorf("healthPolicy field 'isHealth' must be a boolean expression, got %T", v)
+		}
+		return nil
+	}
+
+	found, err := FindAndValidateField(sl, "isHealth", validator)
+	if err != nil {
+		return err
+	}
+	if !found {
+		return fmt.Errorf("healthPolicy must contain an 'isHealth' field")
+	}
+
+	return nil
+}
diff --git a/pkg/definition/ast/utils.go b/pkg/definition/ast/utils.go
index 946ff614..e499aaad 100644
--- a/pkg/definition/ast/utils.go
+++ b/pkg/definition/ast/utils.go
@@ -104,50 +104,40 @@ func StringifyStructLitAsCueString(structLit *ast.StructLit) (*ast.BasicLit, err
 		}, nil
 	}
 
-	var sb strings.Builder
-	sb.WriteString(`#"""`)
-	sb.WriteString("\n")
-
-	for _, elt := range structLit.Elts {
-		field, ok := elt.(*ast.Field)
-		if !ok {
-			continue
-		}
-
-		var labelStr, valueStr string
-
-		switch l := field.Label.(type) {
-		case *ast.Ident:
-			labelStr = l.Name
-		case *ast.BasicLit:
-			labelStr = strings.Trim(l.Value, `"`)
-		default:
-			labelStr = "<unknown>"
-		}
+	formatted, err := format.Node(structLit)
+	if err != nil {
+		return nil, fmt.Errorf("failed to format struct: %w", err)
+	}
 
-		for _, attr := range field.Attrs {
-			sb.WriteString("  " + attr.Text + "\n")
-		}
+	content := string(formatted)
 
-		b, err := format.Node(field.Value)
-		if err != nil {
-			valueStr = "<complex>"
-		} else {
-			lines := strings.Split(string(b), "\n")
-			for i := range lines {
-				lines[i] = "  " + lines[i]
-			}
-			valueStr = strings.Join(lines, "\n")
-		}
+	content = strings.TrimSpace(content)
+	if strings.HasPrefix(content, "{") && strings.HasSuffix(content, "}") {
+		content = strings.TrimPrefix(content, "{")
+		content = strings.TrimSuffix(content, "}")
+		content = strings.Trim(content, "\n")
+	}
 
-		sb.WriteString(fmt.Sprintf("  %s: %s\n", labelStr, valueStr))
+	if content == "" {
+		return &ast.BasicLit{
+			Kind:  token.STRING,
+			Value: `"{}"`,
+		}, nil
 	}
+	lines := strings.Split(content, "\n")
 
+	var sb strings.Builder
+	sb.WriteString(`#"""`)
+	sb.WriteString("\n")
+	sb.WriteString(strings.Join(lines, "\n"))
+	sb.WriteString("\n")
 	sb.WriteString(`"""#`)
-	val := strings.ReplaceAll(sb.String(), "\t", "  ")
+
+	result := strings.ReplaceAll(sb.String(), "\t", "  ")
+
 	return &ast.BasicLit{
 		Kind:  token.STRING,
-		Value: val,
+		Value: result,
 	}, nil
 }
 
@@ -177,20 +167,26 @@ func ValidateCueStringLiteral[T ast.Node](lit *ast.BasicLit, validator func(T) e
 	return validator(node)
 }
 
-// TrimCueRawString trims a CUE raw string literal
+// TrimCueRawString trims a CUE raw string literal and handles escape sequences
 func TrimCueRawString(s string) string {
 	s = strings.TrimSpace(s)
-	if strings.HasPrefix(s, `#"""`) && strings.HasSuffix(s, `"""#`) {
-		return strings.TrimSuffix(strings.TrimPrefix(s, `#"""`), `"""#`)
-	}
-	if strings.HasPrefix(s, `"""`) && strings.HasSuffix(s, `"""`) {
-		return strings.TrimSuffix(strings.TrimPrefix(s, `"""`), `"""`)
-	}
-	fallback, err := strconv.Unquote(s)
-	if err != nil {
-		return s
+	switch {
+	case strings.HasPrefix(s, `#"""`) && strings.HasSuffix(s, `"""#`):
+		s = strings.TrimSuffix(strings.TrimPrefix(s, `#"""`), `"""#`)
+	case strings.HasPrefix(s, `"""`) && strings.HasSuffix(s, `"""`):
+		s = strings.TrimSuffix(strings.TrimPrefix(s, `"""`), `"""`)
+	default:
+		fallback, err := strconv.Unquote(s)
+		if err == nil {
+			s = fallback
+		}
 	}
-	return fallback
+
+	// Handle escape sequences for backward compatibility with existing definitions
+	s = strings.ReplaceAll(s, "\\t", "  ")
+	s = strings.ReplaceAll(s, "\\\\", "\\")
+
+	return s
 }
 
 // WrapCueStruct wraps a string in a CUE struct format
@@ -198,6 +194,48 @@ func WrapCueStruct(s string) string {
 	return fmt.Sprintf("{\n%s\n}", s)
 }
 
+// FindAndValidateField searches for a field at the top level or within top-level if statements
+func FindAndValidateField(sl *ast.StructLit, fieldName string, validator fieldValidator) (found bool, err error) {
+	// First check top-level fields
+	for _, elt := range sl.Elts {
+		if field, ok := elt.(*ast.Field); ok {
+			label := GetFieldLabel(field.Label)
+			if label == fieldName {
+				found = true
+				if validator != nil {
+					err = validator(field.Value)
+				}
+				return found, err
+			}
+		}
+	}
+
+	// If not found at top level, check within top-level if statements
+	for _, elt := range sl.Elts {
+		if comp, ok := elt.(*ast.Comprehension); ok {
+			// Check if this comprehension has if clauses (conditional fields)
+			hasIfClause := false
+			for _, clause := range comp.Clauses {
+				if _, ok := clause.(*ast.IfClause); ok {
+					hasIfClause = true
+					break
+				}
+			}
+
+			// If it has an if clause and the value is a struct, search within it
+			if hasIfClause {
+				if structLit, ok := comp.Value.(*ast.StructLit); ok {
+					if innerFound, innerErr := FindAndValidateField(structLit, fieldName, validator); innerFound {
+						return true, innerErr
+					}
+				}
+			}
+		}
+	}
+
+	return found, err
+}
+
 func lookupTopLevelField(node ast.Node, key string) (*ast.Field, ast.Expr, bool) {
 	switch n := node.(type) {
 	case *ast.Field:
@@ -220,6 +258,9 @@ func lookupTopLevelField(node ast.Node, key string) (*ast.Field, ast.Expr, bool)
 	return nil, nil, false
 }
 
+// fieldValidator is a function that validates a field's value
+type fieldValidator func(ast.Expr) error
+
 func traversePath(val ast.Expr, pathParts []string, lastField *ast.Field) (ast.Node, *ast.Field, bool) {
 	currentField := lastField
 	currentVal := val
diff --git a/pkg/workflow/step/generator.go b/pkg/workflow/step/generator.go
index 243ba003..818b4198 100644
--- a/pkg/workflow/step/generator.go
+++ b/pkg/workflow/step/generator.go
@@ -96,6 +96,7 @@ func (g *ApplyComponentWorkflowStepGenerator) Generate(app *v1beta1.Application,
 				Properties: util.Object2RawExtension(map[string]string{
 					"component": comp.Name,
 				}),
+				DependsOn: comp.DependsOn,
 			},
 		})
 	}
diff --git a/references/appfile/api/service.go b/references/appfile/api/service.go
index 05ad0e27..e4028fa9 100644
--- a/references/appfile/api/service.go
+++ b/references/appfile/api/service.go
@@ -94,7 +94,11 @@ func (s Service) RenderServiceToApplicationComponent(tm template.Manager, servic
 			traits = append(traits, trait)
 			continue
 		}
-		workloadKeys[k] = v
+		if k != "dependsOn" {
+			workloadKeys[k] = v
+		} else {
+			comp.DependsOn = toStringSlice(v)
+		}
 	}
 
 	// Handle workloadKeys to settings
@@ -115,6 +119,26 @@ func (s Service) RenderServiceToApplicationComponent(tm template.Manager, servic
 	return comp, nil
 }
 
+// toStringSlice converts an interface{} or string to a []string
+func toStringSlice(v interface{}) []string {
+	switch val := v.(type) {
+	case string:
+		return []string{val}
+	case []string:
+		return val
+	case []interface{}:
+		var result []string
+		for _, item := range val {
+			if s, ok := item.(string); ok {
+				result = append(result, s)
+			}
+		}
+		return result
+	default:
+		return nil
+	}
+}
+
 // GetServices will get all services defined in AppFile
 func (af *AppFile) GetServices() map[string]Service {
 	return af.Services



Test patch:
diff --git a/e2e/application/application_test.go b/e2e/application/application_test.go
index 46adcc8c..4b0b781e 100644
--- a/e2e/application/application_test.go
+++ b/e2e/application/application_test.go
@@ -44,20 +44,23 @@ var (
 	applicationName             = "app-basic"
 	traitAlias                  = "scaler"
 	appNameForInit              = "initmyapp"
-	jsonAppFile                 = `{"name":"nginx-vela","services":{"nginx":{"type":"webservice","image":"nginx:1.9.4","ports":[{port: 80, expose: true}]}}}`
-	testDeleteJsonAppFile       = `{"name":"test-vela-delete","services":{"nginx-test":{"type":"webservice","image":"nginx:1.9.4","ports":[{port: 80, expose: true}]}}}`
-	appbasicJsonAppFile         = `{"name":"app-basic","services":{"app-basic":{"type":"webservice","image":"nginx:1.9.4","ports":[{port: 80, expose: true}]}}}`
-	appbasicAddTraitJsonAppFile = `{"name":"app-basic","services":{"app-basic":{"type":"webservice","image":"nginx:1.9.4","ports":[{port: 80, expose: true}],"scaler":{"replicas":2}}}}`
+	jsonAppFile                 = `{"name":"nginx-vela","services":{"nginx":{"type":"webservice","image":"nginx:1.29.0","ports":[{port: 80, expose: true}]}}}`
+	testDeleteJsonAppFile       = `{"name":"test-vela-delete","services":{"nginx-test":{"type":"webservice","image":"nginx:1.29.0","ports":[{port: 80, expose: true}]}}}`
+	appbasicJsonAppFile         = `{"name":"app-basic","services":{"app-basic":{"type":"webservice","image":"nginx:1.29.0","ports":[{port: 80, expose: true}]}}}`
+	appbasicAddTraitJsonAppFile = `{"name":"app-basic","services":{"app-basic":{"type":"webservice","image":"nginx:1.29.0","ports":[{port: 80, expose: true}],"scaler":{"replicas":2}}}}`
 	velaQL                      = "test-component-pod-view{appNs=default,appName=nginx-vela,name=nginx}"
 
-	waitAppfileToSuccess = `{"name":"app-wait-success","services":{"app-basic1":{"type":"webservice","image":"nginx:1.9.4","ports":[{port: 80, expose: true}]}}}`
+	waitAppfileToSuccess = `{"name":"app-wait-success","services":{"app-basic1":{"type":"webservice","image":"nginx:1.29.0","ports":[{port: 80, expose: true}]}}}`
 	waitAppfileToFail    = `{"name":"app-wait-fail","services":{"app-basic2":{"type":"webservice","image":"nginx:fail","ports":[{port: 80, expose: true}]}}}`
+
+	componentDependsOnFailApp     = `{"name":"comp-depends-fail","services":{"failing-db":{"type":"webservice","image": ""},"dependent-service":{"type":"webservice","dependsOn":["failing-db"],"image":"nginx:latest","ports":[{"port":8080,"expose":false}]}}}`
+	componentDependsOnMultipleApp = `{"name":"comp-depends-multiple","services":{"database":{"type":"webservice","image":"nginx:latest","ports":[{"port":3306,"expose":false}]},"cache":{"type":"webservice","image":"nginx:latest","ports":[{"port":6379,"expose":false}]},"backend":{"type":"webservice","dependsOn":["database","cache"],"image":"nginx:latest","ports":[{"port":8080,"expose":false}]}}}`
 )
 
 var _ = ginkgo.Describe("Test Vela Application", ginkgo.Ordered, func() {
+	e2e.DeleteEnvFunc("env delete", envName)
 	e2e.JsonAppFileContext("json appfile apply", jsonAppFile)
 	e2e.EnvSetContext("env set default", "default")
-	e2e.DeleteEnvFunc("env delete", envName)
 	e2e.EnvInitContext("env init env-application", envName)
 	e2e.EnvSetContext("env set", envName)
 	e2e.JsonAppFileContext("deploy app-basic", appbasicJsonAppFile)
@@ -313,3 +316,61 @@ var VelaQLPodListContext = func(context string, velaQL string) bool {
 		}
 	})
 }
+
+var _ = ginkgo.Describe("Test Component Level DependsOn CLI", ginkgo.Ordered, func() {
+
+	e2e.JsonAppFileContext("component dependsOn failure blocking", componentDependsOnFailApp)
+	ComponentDependsOnFailureContext("component dependsOn failure blocking verification", "comp-depends-fail")
+	e2e.WorkloadDeleteContext("delete failure app", "comp-depends-fail")
+
+	e2e.JsonAppFileContext("component dependsOn multiple dependencies", componentDependsOnMultipleApp)
+	ComponentDependsOnMultipleContext("component dependsOn multiple dependencies verification", "comp-depends-multiple")
+	e2e.WorkloadDeleteContext("delete multiple deps app", "comp-depends-multiple")
+})
+
+var ComponentDependsOnFailureContext = func(context string, appName string) bool {
+	return ginkgo.It(context+": should block dependent components when dependency fails", func() {
+		ginkgo.By("verify application doesn't reach running state due to component failure")
+		ginkgo.By("wait sufficient time for dependency check")
+		time.Sleep(45 * time.Second)
+
+		cli := fmt.Sprintf("vela status %s", appName)
+		output, err := e2e.Exec(cli)
+		gomega.Expect(err).NotTo(gomega.HaveOccurred())
+
+		ginkgo.By("check that dependent service is blocked")
+		gomega.Expect(strings.ToLower(output)).Should(gomega.ContainSubstring("failed"))
+		// The app should show some indication that components are waiting on dependencies
+		gomega.Expect(strings.ToLower(output)).Should(gomega.SatisfyAny(
+			gomega.ContainSubstring("pending"),
+			gomega.ContainSubstring("progressing"),
+			gomega.ContainSubstring("waiting"),
+			gomega.ContainSubstring("suspend"),
+		))
+	})
+}
+
+var ComponentDependsOnMultipleContext = func(context string, appName string) bool {
+	return ginkgo.It(context+": should handle multiple dependencies correctly", func() {
+		ginkgo.By("verify application eventually reaches running state")
+		gomega.Eventually(func() string {
+			cli := fmt.Sprintf("vela status %s", appName)
+			output, err := e2e.Exec(cli)
+			gomega.Expect(err).NotTo(gomega.HaveOccurred())
+			return output
+		}, 300*time.Second, 5*time.Second).Should(gomega.ContainSubstring("running"))
+
+		ginkgo.By("wait sufficient time for dependency check")
+		time.Sleep(time.Minute)
+
+		ginkgo.By("verify all components are healthy")
+		cli := fmt.Sprintf("vela status %s --tree", appName)
+		output, err := e2e.Exec(cli)
+		gomega.Expect(err).NotTo(gomega.HaveOccurred())
+		gomega.Expect(output).Should(gomega.And(
+			gomega.ContainSubstring("database"),
+			gomega.ContainSubstring("cache"),
+			gomega.ContainSubstring("backend"),
+		))
+	})
+}
diff --git a/pkg/definition/ast/transformer_test.go b/pkg/definition/ast/transformer_test.go
index d177c8bc..3c99b457 100644
--- a/pkg/definition/ast/transformer_test.go
+++ b/pkg/definition/ast/transformer_test.go
@@ -229,3 +229,891 @@ func TestMarshalAndUnmarshalMetadata(t *testing.T) {
 		})
 	}
 }
+
+func TestMarshalAndUnmarshalHealthPolicy(t *testing.T) {
+	tests := []struct {
+		name               string
+		input              string
+		expectMarshalErr   string
+		expectUnmarshalErr string
+		expectContains     string
+	}{
+		{
+			name: "valid healthPolicy with boolean literal",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: true
+						}
+					}
+				}
+			`,
+			expectContains: "isHealth",
+		},
+		{
+			name: "valid healthPolicy with binary expression",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: context.output.status.phase == "Running"
+						}
+					}
+				}
+			`,
+			expectContains: "isHealth",
+		},
+		{
+			name: "valid healthPolicy with complex expression",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: context.output.status.ready && context.output.status.replicas > 0
+						}
+					}
+				}
+			`,
+			expectContains: "isHealth",
+		},
+		{
+			name: "valid healthPolicy with selector expression",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: context.output.status.conditions[0].status
+						}
+					}
+				}
+			`,
+			expectContains: "isHealth",
+		},
+		{
+			name: "valid healthPolicy with call expression",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: len(context.output.status.conditions) > 0
+						}
+					}
+				}
+			`,
+			expectContains: "isHealth",
+		},
+		{
+			name: "healthPolicy missing isHealth field",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							someOtherField: true
+						}
+					}
+				}
+			`,
+			expectMarshalErr: "healthPolicy must contain an 'isHealth' field",
+		},
+		{
+			name: "healthPolicy with invalid isHealth type (struct)",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: { nested: true }
+						}
+					}
+				}
+			`,
+			expectMarshalErr: "healthPolicy field 'isHealth' must be a boolean expression",
+		},
+		{
+			name: "healthPolicy with invalid isHealth type (list)",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: [true, false]
+						}
+					}
+				}
+			`,
+			expectMarshalErr: "healthPolicy field 'isHealth' must be a boolean expression",
+		},
+		{
+			name: "valid stringified healthPolicy round trip",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: #"""
+							isHealth: context.output.status.phase == "Running"
+						"""#
+					}
+				}
+			`,
+			expectContains: "isHealth",
+		},
+		{
+			name: "malformed stringified healthPolicy fails validation",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: #"""
+							invalid cue: abc
+						"""#
+					}
+				}
+			`,
+			expectMarshalErr: "invalid cue content in string literal",
+		},
+		{
+			name: "healthPolicy as plain string is valid",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: "isHealth: true"
+					}
+				}
+			`,
+			expectContains: "isHealth",
+		},
+	}
+
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			file, err := parser.ParseFile("-", tt.input)
+			require.NoError(t, err)
+
+			var rootField *ast.Field
+			for _, decl := range file.Decls {
+				if f, ok := decl.(*ast.Field); ok {
+					rootField = f
+					break
+				}
+			}
+			require.NotNil(t, rootField)
+
+			err = EncodeMetadata(rootField)
+			if tt.expectMarshalErr != "" {
+				require.Error(t, err)
+				require.Contains(t, err.Error(), tt.expectMarshalErr)
+				return
+			} else {
+				require.NoError(t, err)
+			}
+
+			err = DecodeMetadata(rootField)
+			if tt.expectUnmarshalErr != "" {
+				require.Error(t, err)
+				require.Contains(t, err.Error(), tt.expectUnmarshalErr)
+				return
+			} else {
+				require.NoError(t, err)
+			}
+
+			if tt.expectContains != "" {
+				healthPolicyField, ok := GetFieldByPath(rootField, "attributes.status.healthPolicy")
+				require.True(t, ok)
+
+				switch v := healthPolicyField.Value.(type) {
+				case *ast.BasicLit:
+					require.Contains(t, v.Value, tt.expectContains)
+				case *ast.StructLit:
+					out, err := format.Node(v)
+					require.NoError(t, err)
+					require.Contains(t, string(out), tt.expectContains)
+				default:
+					t.Fatalf("unexpected healthPolicy value type: %T", v)
+				}
+			}
+		})
+	}
+}
+
+func TestMarshalAndUnmarshalCustomStatus(t *testing.T) {
+	tests := []struct {
+		name               string
+		input              string
+		expectMarshalErr   string
+		expectUnmarshalErr string
+		expectContains     string
+	}{
+		{
+			name: "valid customStatus with string message",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: "Service is healthy"
+						}
+					}
+				}
+			`,
+			expectContains: "message",
+		},
+		{
+			name: "valid customStatus with interpolation",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: "\(context.output.metadata.name) is running"
+						}
+					}
+				}
+			`,
+			expectContains: "message",
+		},
+		{
+			name: "valid customStatus with selector expression",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: context.output.status.message
+						}
+					}
+				}
+			`,
+			expectContains: "message",
+		},
+		{
+			name: "valid customStatus with binary expression",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: "Replicas: " + context.output.status.replicas
+						}
+					}
+				}
+			`,
+			expectContains: "message",
+		},
+		{
+			name: "valid customStatus with call expression",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: strconv.FormatInt(context.output.status.replicas, 10)
+						}
+					}
+				}
+			`,
+			expectContains: "message",
+		},
+		{
+			name: "valid customStatus with list expression",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: [for c in context.output.status.conditions if c.type == "Ready" { c.message }][0]
+						}
+					}
+				}
+			`,
+			expectContains: "message",
+		},
+		{
+			name: "customStatus missing message field",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							someOtherField: "value"
+						}
+					}
+				}
+			`,
+			expectMarshalErr: "customStatus must contain a 'message' field",
+		},
+		{
+			name: "customStatus with invalid message type (struct)",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: { nested: "value" }
+						}
+					}
+				}
+			`,
+			expectMarshalErr: "customStatus field 'message' must be a string expression",
+		},
+		{
+			name: "customStatus with integer literal message",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: 42
+						}
+					}
+				}
+			`,
+			expectMarshalErr: "customStatus field 'message' must be a string",
+		},
+		{
+			name: "valid stringified customStatus round trip",
+			input: `
+				attributes: {
+					status: {
+						customStatus: #"""
+							message: "Pod \(context.output.metadata.name) is running"
+						"""#
+					}
+				}
+			`,
+			expectContains: "message",
+		},
+		{
+			name: "malformed stringified customStatus fails validation",
+			input: `
+				attributes: {
+					status: {
+						customStatus: #"""
+							invalid cue: abc
+						"""#
+					}
+				}
+			`,
+			expectMarshalErr: "invalid cue content in string literal",
+		},
+		{
+			name: "customStatus with additional fields alongside message",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: "Service is healthy"
+							severity: "info"
+							timestamp: context.output.metadata.creationTimestamp
+						}
+					}
+				}
+			`,
+			expectContains: "message",
+		},
+		{
+			name: "customStatus as plain string is valid",
+			input: `
+				attributes: {
+					status: {
+						customStatus: "message: \"Hello\""
+					}
+				}
+			`,
+			expectContains: "message",
+		},
+	}
+
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			file, err := parser.ParseFile("-", tt.input)
+			require.NoError(t, err)
+
+			var rootField *ast.Field
+			for _, decl := range file.Decls {
+				if f, ok := decl.(*ast.Field); ok {
+					rootField = f
+					break
+				}
+			}
+			require.NotNil(t, rootField)
+
+			err = EncodeMetadata(rootField)
+			if tt.expectMarshalErr != "" {
+				require.Error(t, err)
+				require.Contains(t, err.Error(), tt.expectMarshalErr)
+				return
+			} else {
+				require.NoError(t, err)
+			}
+
+			err = DecodeMetadata(rootField)
+			if tt.expectUnmarshalErr != "" {
+				require.Error(t, err)
+				require.Contains(t, err.Error(), tt.expectUnmarshalErr)
+				return
+			} else {
+				require.NoError(t, err)
+			}
+
+			if tt.expectContains != "" {
+				customStatusField, ok := GetFieldByPath(rootField, "attributes.status.customStatus")
+				require.True(t, ok)
+
+				switch v := customStatusField.Value.(type) {
+				case *ast.BasicLit:
+					require.Contains(t, v.Value, tt.expectContains)
+				case *ast.StructLit:
+					out, err := format.Node(v)
+					require.NoError(t, err)
+					require.Contains(t, string(out), tt.expectContains)
+				default:
+					t.Fatalf("unexpected customStatus value type: %T", v)
+				}
+			}
+		})
+	}
+}
+
+func TestHealthPolicyEdgeCases(t *testing.T) {
+	tests := []struct {
+		name               string
+		input              string
+		expectMarshalErr   string
+		expectUnmarshalErr string
+	}{
+		{
+			name: "healthPolicy with unary expression",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: !context.output.status.failed
+						}
+					}
+				}
+			`,
+		},
+		{
+			name: "healthPolicy with parenthesized expression",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: (context.output.status.phase == "Running" || context.output.status.phase == "Succeeded")
+						}
+					}
+				}
+			`,
+		},
+		{
+			name: "healthPolicy with nested binary expressions",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: context.output.status.ready && (context.output.status.replicas > 0 || context.output.status.phase == "Ready")
+						}
+					}
+				}
+			`,
+		},
+		{
+			name: "healthPolicy with string literal should fail",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: "true"
+						}
+					}
+				}
+			`,
+			expectMarshalErr: "healthPolicy field 'isHealth' must be a boolean literal (true/false)",
+		},
+		{
+			name: "healthPolicy with comprehension should fail",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: [for c in context.output.status.conditions if c.type == "Ready" { c.status }][0]
+						}
+					}
+				}
+			`,
+			expectMarshalErr: "healthPolicy field 'isHealth' must be a boolean expression",
+		},
+		{
+			name: "healthPolicy with empty struct should fail",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {}
+					}
+				}
+			`,
+			expectMarshalErr: "healthPolicy must contain an 'isHealth' field",
+		},
+		{
+			name: "healthPolicy with additional fields is allowed",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: {
+							isHealth: true
+							reason: "always healthy"
+						}
+					}
+				}
+			`,
+		},
+	}
+
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			file, err := parser.ParseFile("-", tt.input)
+			require.NoError(t, err)
+
+			var rootField *ast.Field
+			for _, decl := range file.Decls {
+				if f, ok := decl.(*ast.Field); ok {
+					rootField = f
+					break
+				}
+			}
+			require.NotNil(t, rootField)
+
+			err = EncodeMetadata(rootField)
+			if tt.expectMarshalErr != "" {
+				require.Error(t, err)
+				require.Contains(t, err.Error(), tt.expectMarshalErr)
+				return
+			} else {
+				require.NoError(t, err)
+			}
+
+			err = DecodeMetadata(rootField)
+			if tt.expectUnmarshalErr != "" {
+				require.Error(t, err)
+				require.Contains(t, err.Error(), tt.expectUnmarshalErr)
+				return
+			} else {
+				require.NoError(t, err)
+			}
+		})
+	}
+}
+
+func TestCustomStatusEdgeCases(t *testing.T) {
+	tests := []struct {
+		name               string
+		input              string
+		expectMarshalErr   string
+		expectUnmarshalErr string
+	}{
+		{
+			name: "customStatus with comprehension expression",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: [for i, v in context.output.status.conditions { "\(i): \(v.message)" }][0]
+						}
+					}
+				}
+			`,
+		},
+		{
+			name: "customStatus with index expression",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: context.output.status.conditions[0].message
+						}
+					}
+				}
+			`,
+		},
+		{
+			name: "customStatus with slice expression",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: context.output.status.message[0:10]
+						}
+					}
+				}
+			`,
+		},
+		{
+			name: "customStatus with parenthesized expression",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: ("Status: " + context.output.status.phase)
+						}
+					}
+				}
+			`,
+		},
+		{
+			name: "customStatus with nested interpolation",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: "Pod \(context.output.metadata.name) has \(context.output.status.replicas) replicas"
+						}
+					}
+				}
+			`,
+		},
+		{
+			name: "customStatus with boolean literal should fail",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: true
+						}
+					}
+				}
+			`,
+			expectMarshalErr: "customStatus field 'message' must be a string",
+		},
+		{
+			name: "customStatus with empty struct should fail",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {}
+					}
+				}
+			`,
+			expectMarshalErr: "customStatus must contain a 'message' field",
+		},
+		{
+			name: "customStatus with only non-message fields should fail",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							severity: "error"
+							code: 500
+						}
+					}
+				}
+			`,
+			expectMarshalErr: "customStatus must contain a 'message' field",
+		},
+		{
+			name: "customStatus with field expression should fail",
+			input: `
+				attributes: {
+					status: {
+						customStatus: {
+							message: { template: "Hello" }
+						}
+					}
+				}
+			`,
+			expectMarshalErr: "customStatus field 'message' must be a string expression",
+		},
+	}
+
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			file, err := parser.ParseFile("-", tt.input)
+			require.NoError(t, err)
+
+			var rootField *ast.Field
+			for _, decl := range file.Decls {
+				if f, ok := decl.(*ast.Field); ok {
+					rootField = f
+					break
+				}
+			}
+			require.NotNil(t, rootField)
+
+			err = EncodeMetadata(rootField)
+			if tt.expectMarshalErr != "" {
+				require.Error(t, err)
+				require.Contains(t, err.Error(), tt.expectMarshalErr)
+				return
+			} else {
+				require.NoError(t, err)
+			}
+
+			err = DecodeMetadata(rootField)
+			if tt.expectUnmarshalErr != "" {
+				require.Error(t, err)
+				require.Contains(t, err.Error(), tt.expectUnmarshalErr)
+				return
+			} else {
+				require.NoError(t, err)
+			}
+		})
+	}
+}
+
+func TestBackwardCompatibility(t *testing.T) {
+	tests := []struct {
+		name  string
+		input string
+	}{
+		{
+			name: "existing worker component healthPolicy format",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: #"""
+							isHealth: context.output.status.readyReplicas > 0 && context.output.status.readyReplicas == context.output.status.replicas
+						"""#
+					}
+				}
+			`,
+		},
+		{
+			name: "existing worker component customStatus format",
+			input: `
+				attributes: {
+					status: {
+						customStatus: #"""
+							appName:     context.appName
+							internal:    "\($appName) is running"
+							exposeType:  *"" | string
+							if context.outputs.service != _|_ {
+								exposeType: context.outputs.service.spec.type
+							}
+							if exposeType == "ClusterIP" {
+								message: "\(appName) has ClusterIP service"
+							}
+							if exposeType == "NodePort" {
+								message: "\(appName) has NodePort service"
+							}
+							if exposeType == "LoadBalancer" {
+								message: "\(appName) has LoadBalancer service"
+							}
+							if exposeType == "" {
+								message: internal
+							}
+						"""#
+					}
+				}
+			`,
+		},
+		{
+			name: "complex multi-field definition with both healthPolicy and customStatus",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: #"""
+							isHealth: context.output.status.phase == "Running" || (context.output.status.phase == "Succeeded" && context.output.spec.restartPolicy == "Never")
+						"""#
+						customStatus: #"""
+							ready: [ for c in context.output.status.conditions if c.type == "Ready" { c.status }][0] == "True"
+							message: "Pod \(context.output.metadata.name): phase=\(context.output.status.phase), ready=\(ready)"
+						"""#
+					}
+				}
+			`,
+		},
+		{
+			name: "simple string format for healthPolicy",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: "isHealth: true"
+					}
+				}
+			`,
+		},
+		{
+			name: "simple string format for customStatus",
+			input: `
+				attributes: {
+					status: {
+						customStatus: "message: \"Service is healthy\""
+					}
+				}
+			`,
+		},
+		{
+			name: "healthPolicy with list comprehensions and complex conditions",
+			input: `
+				attributes: {
+					status: {
+						healthPolicy: #"""
+							conditions: [ for c in context.output.status.conditions if c.type == "Ready" || c.type == "ContainersReady" { c.status }]
+							isHealth: len($conditions) > 0 && ![ for c in conditions if c != "True" { c }] != []
+						"""#
+					}
+				}
+			`,
+		},
+		{
+			name: "customStatus with nested conditionals and string interpolation",
+			input: `
+				attributes: {
+					status: {
+						customStatus: #"""
+							phase: context.output.status.phase
+							replicas: context.output.status.replicas
+							readyReplicas: *0 | int
+							if context.output.status.readyReplicas != _|_ {
+								readyReplicas: context.output.status.readyReplicas
+							}
+							if phase == "Running" {
+								if readyReplicas == replicas {
+									message: "All \(replicas) replicas are ready"
+								}
+								if readyReplicas < replicas {
+									message: "Only \(readyReplicas) of \(replicas) replicas are ready"
+								}
+							}
+							if phase != "Running" {
+								message: "Deployment is in phase: \(phase)"
+							}
+						"""#
+					}
+				}
+			`,
+		},
+		{
+			name: "preserving local fields that start with $",
+			input: `
+				attributes: {
+					status: {
+						customStatus: #"""
+							internal: "internal state"
+							compute: context.output.status.replicas * 2
+							debugInfo: {
+								phase: context.output.status.phase
+								replicas: context.output.status.replicas
+							}
+							message: "Status: \(internal), computed: \(compute)"
+						"""#
+					}
+				}
+			`,
+		},
+	}
+
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			file, err := parser.ParseFile("-", tt.input)
+			require.NoError(t, err)
+
+			var rootField *ast.Field
+			for _, decl := range file.Decls {
+				if f, ok := decl.(*ast.Field); ok {
+					rootField = f
+					break
+				}
+			}
+			require.NotNil(t, rootField)
+
+			err = EncodeMetadata(rootField)
+			require.NoError(t, err)
+
+			err = DecodeMetadata(rootField)
+			require.NoError(t, err)
+		})
+	}
+}
diff --git a/pkg/definition/ast/utils_test.go b/pkg/definition/ast/utils_test.go
index b2494aeb..f9f8c739 100644
--- a/pkg/definition/ast/utils_test.go
+++ b/pkg/definition/ast/utils_test.go
@@ -281,6 +281,25 @@ func TestStringifyStructLitAsCueString(t *testing.T) {
 			}`,
 			shouldFail: true,
 		},
+		{
+			name: "Conditional fields with if statements",
+			input: `
+			{
+				if context.status.healthy {
+					message: "Healthy! (\(context.status.details.replicaReadyRatio * 100)% pods running)"
+				}
+
+				if !context.status.healthy {
+					message: "Unhealthy! (\(context.status.details.replicaReadyRatio * 100)% pods running)"
+				}
+			}`,
+			contains: []string{
+				`if context.status.healthy {`,
+				`message: "Healthy! (\(context.status.details.replicaReadyRatio*100)% pods running)"`,
+				`if !context.status.healthy {`,
+				`message: "Unhealthy! (\(context.status.details.replicaReadyRatio*100)% pods running)"`,
+			},
+		},
 	}
 
 	for _, tt := range tests {
@@ -536,3 +555,270 @@ func TestWrapCueStruct(t *testing.T) {
 		})
 	}
 }
+
+func TestFindAndValidateField(t *testing.T) {
+	tests := []struct {
+		name               string
+		input              string
+		fieldName          string
+		expectedFound      bool
+		expectedErrMessage string
+		validator          fieldValidator
+	}{
+		{
+			name: "find field at top level without validator",
+			input: `{
+				field1: "value1"
+				field2: "value2"
+			}`,
+			fieldName:     "field1",
+			expectedFound: true,
+		},
+		{
+			name: "field not found at any level",
+			input: `{
+				field1: "value1"
+				field2: "value2"
+			}`,
+			fieldName:     "field3",
+			expectedFound: false,
+		},
+		{
+			name: "find field at top level with validator that passes",
+			input: `{
+				message: "hello world"
+				other: "value"
+			}`,
+			fieldName:     "message",
+			expectedFound: true,
+			validator: func(expr ast.Expr) error {
+				if basicLit, ok := expr.(*ast.BasicLit); ok {
+					if basicLit.Value != `"hello world"` {
+						return fmt.Errorf("expected hello world, got %s", basicLit.Value)
+					}
+				}
+				return nil
+			},
+		},
+		{
+			name: "find field at top level with validator that fails",
+			input: `{
+				message: "hello world"
+				other: "value"
+			}`,
+			fieldName:          "message",
+			expectedFound:      true,
+			expectedErrMessage: "expected goodbye, got",
+			validator: func(expr ast.Expr) error {
+				if basicLit, ok := expr.(*ast.BasicLit); ok {
+					if basicLit.Value != `"goodbye"` {
+						return fmt.Errorf("expected goodbye, got %s", basicLit.Value)
+					}
+				}
+				return nil
+			},
+		},
+		{
+			name: "find field in simple if statement",
+			input: `{
+				otherField: "value"
+				if condition {
+					message: "found in if"
+				}
+			}`,
+			fieldName:     "message",
+			expectedFound: true,
+		},
+		{
+			name: "find field in nested if statements",
+			input: `{
+				otherField: "value"
+				if condition1 {
+					if condition2 {
+						message: "deeply nested"
+					}
+				}
+			}`,
+			fieldName:     "message",
+			expectedFound: true,
+		},
+		{
+			name: "find field in if-else chain",
+			input: `{
+				status: "running"
+				if status == "running" {
+					message: "service is running"
+				}
+				if status == "stopped" {
+					message: "service is stopped"
+				}
+			}`,
+			fieldName:     "message",
+			expectedFound: true,
+		},
+		{
+			name: "find field in complex nested conditionals",
+			input: `{
+				phase: context.output.status.phase
+				replicas: context.output.status.replicas
+				readyReplicas: *0 | int
+				if context.output.status.readyReplicas != _|_ {
+					readyReplicas: context.output.status.readyReplicas
+				}
+				if phase == "Running" {
+					if readyReplicas == replicas {
+						message: "All replicas are ready"
+					}
+					if readyReplicas < replicas {
+						message: "Some replicas are not ready"
+					}
+				}
+				if phase != "Running" {
+					message: "Deployment is not running"
+				}
+			}`,
+			fieldName:     "message",
+			expectedFound: true,
+		},
+		{
+			name: "find field in if with validator",
+			input: `{
+				condition: true
+				if condition {
+					isHealth: true
+				}
+			}`,
+			fieldName:     "isHealth",
+			expectedFound: true,
+			validator: func(expr ast.Expr) error {
+				if basicLit, ok := expr.(*ast.BasicLit); ok {
+					if basicLit.Value != "true" {
+						return fmt.Errorf("expected true, got %s", basicLit.Value)
+					}
+				}
+				return nil
+			},
+		},
+		{
+			name: "find field in nested if with failing validator",
+			input: `{
+				condition: true
+				if condition {
+					if nestedCondition {
+						isHealth: false
+					}
+				}
+			}`,
+			fieldName:          "isHealth",
+			expectedFound:      true,
+			expectedErrMessage: "expected true, got",
+			validator: func(expr ast.Expr) error {
+				if basicLit, ok := expr.(*ast.BasicLit); ok {
+					if basicLit.Value != "true" {
+						return fmt.Errorf("expected true, got %s", basicLit.Value)
+					}
+				}
+				return nil
+			},
+		},
+		{
+			name: "field not found in comprehension without if clause",
+			input: `{
+				items: [for x in list { value: x }]
+			}`,
+			fieldName:     "message",
+			expectedFound: false,
+		},
+		{
+			name: "find field with complex expressions in if",
+			input: `{
+				replicas: context.output.status.replicas
+				readyReplicas: context.output.status.readyReplicas
+				if (replicas | *0) != (readyReplicas | *0) {
+					message: "not ready"
+				}
+			}`,
+			fieldName:     "message",
+			expectedFound: true,
+		},
+		{
+			name: "find field with quoted label in if statement",
+			input: `{
+				condition: true
+				if condition {
+					"field-with-dash": "value"
+				}
+			}`,
+			fieldName:     "field-with-dash",
+			expectedFound: true,
+		},
+		{
+			name: "find field in multiple nested levels",
+			input: `{
+				level1: "value"
+				if condition1 {
+					level2: "value"
+					if condition2 {
+						level3: "value"
+						if condition3 {
+							message: "deeply nested field"
+						}
+					}
+				}
+			}`,
+			fieldName:     "message",
+			expectedFound: true,
+		},
+		{
+			name: "empty struct with if statements",
+			input: `{
+				if condition {
+				}
+			}`,
+			fieldName:     "message",
+			expectedFound: false,
+		},
+		{
+			name: "field exists in both top level and if statement (finds top level first)",
+			input: `{
+				message: "top level"
+				if condition {
+					message: "in if"
+				}
+			}`,
+			fieldName:     "message",
+			expectedFound: true,
+			validator: func(expr ast.Expr) error {
+				if basicLit, ok := expr.(*ast.BasicLit); ok {
+					if basicLit.Value == `"top level"` {
+						return nil
+					}
+					return fmt.Errorf("expected top level message, got %s", basicLit.Value)
+				}
+				return fmt.Errorf("expected string literal")
+			},
+		},
+	}
+
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			expr, err := parser.ParseExpr("-", tt.input)
+			require.NoError(t, err)
+
+			structLit, ok := expr.(*ast.StructLit)
+			require.True(t, ok, "input should parse as struct literal")
+
+			found, err := FindAndValidateField(structLit, tt.fieldName, tt.validator)
+
+			require.Equal(t, tt.expectedFound, found, "found result should match expected")
+
+			if tt.expectedErrMessage != "" {
+				require.Error(t, err)
+				require.Contains(t, err.Error(), tt.expectedErrMessage)
+			} else {
+				require.NoError(t, err)
+			}
+		})
+	}
+}
diff --git a/pkg/definition/definition_test.go b/pkg/definition/definition_test.go
index 18906c0c..e7da3fd8 100644
--- a/pkg/definition/definition_test.go
+++ b/pkg/definition/definition_test.go
@@ -280,13 +280,13 @@ func TestCueNativeStatusFromCueString(t *testing.T) {
 	        }
 	      }
 	      status: {
-	        customStatus: #"""
+	        customStatus: {
 	          message: "\(context.output.status.readyReplicas) / \(context.output.status.replicas) replicas are ready"
-	        """#
+	        }
 
-	        healthPolicy: #"""
+	        healthPolicy: {
 	          isHealth: context.output.status.readyReplicas == context.output.status.replicas
-	        """#
+	        }
 
 	        details: {
 	          $temp: context.output.status.replicas
diff --git a/pkg/utils/apply/apply_resource_test.go b/pkg/utils/apply/apply_resource_test.go
index 941c7f64..76aff691 100644
--- a/pkg/utils/apply/apply_resource_test.go
+++ b/pkg/utils/apply/apply_resource_test.go
@@ -229,7 +229,7 @@ func basicTestDeployment() *appsv1.Deployment {
 					Containers: []corev1.Container{ // array field
 						{
 							Name:  "nginx",
-							Image: "nginx:1.9.4", // normal field without default value
+							Image: "nginx:1.29.0", // normal field without default value
 						},
 					},
 				},
diff --git a/pkg/workflow/step/generator_test.go b/pkg/workflow/step/generator_test.go
index ffb4098c..814bbc6e 100644
--- a/pkg/workflow/step/generator_test.go
+++ b/pkg/workflow/step/generator_test.go
@@ -292,6 +292,288 @@ func TestWorkflowStepGenerator(t *testing.T) {
 	}
 }
 
+func TestApplyComponentWorkflowStepGeneratorWithDependsOn(t *testing.T) {
+	r := require.New(t)
+
+	testCases := map[string]struct {
+		input    []workflowv1alpha1.WorkflowStep
+		app      *v1beta1.Application
+		output   []workflowv1alpha1.WorkflowStep
+		hasError bool
+	}{
+		"component-with-single-dependency": {
+			input: []workflowv1alpha1.WorkflowStep{},
+			app: &v1beta1.Application{
+				Spec: v1beta1.ApplicationSpec{
+					Components: []common.ApplicationComponent{{
+						Name: "database",
+						Type: "webservice",
+					}, {
+						Name:      "backend",
+						Type:      "webservice",
+						DependsOn: []string{"database"},
+					}},
+				},
+			},
+			output: []workflowv1alpha1.WorkflowStep{{
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "database",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"database"}`)},
+				},
+			}, {
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "backend",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"backend"}`)},
+					DependsOn:  []string{"database"},
+				},
+			}},
+		},
+		"component-with-multiple-dependencies": {
+			input: []workflowv1alpha1.WorkflowStep{},
+			app: &v1beta1.Application{
+				Spec: v1beta1.ApplicationSpec{
+					Components: []common.ApplicationComponent{{
+						Name: "database",
+						Type: "webservice",
+					}, {
+						Name: "cache",
+						Type: "webservice",
+					}, {
+						Name:      "backend",
+						Type:      "webservice",
+						DependsOn: []string{"database", "cache"},
+					}},
+				},
+			},
+			output: []workflowv1alpha1.WorkflowStep{{
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "database",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"database"}`)},
+				},
+			}, {
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "cache",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"cache"}`)},
+				},
+			}, {
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "backend",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"backend"}`)},
+					DependsOn:  []string{"database", "cache"},
+				},
+			}},
+		},
+		"component-with-chained-dependencies": {
+			input: []workflowv1alpha1.WorkflowStep{},
+			app: &v1beta1.Application{
+				Spec: v1beta1.ApplicationSpec{
+					Components: []common.ApplicationComponent{{
+						Name: "database",
+						Type: "webservice",
+					}, {
+						Name:      "backend",
+						Type:      "webservice",
+						DependsOn: []string{"database"},
+					}, {
+						Name:      "frontend",
+						Type:      "webservice",
+						DependsOn: []string{"backend"},
+					}},
+				},
+			},
+			output: []workflowv1alpha1.WorkflowStep{{
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "database",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"database"}`)},
+				},
+			}, {
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "backend",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"backend"}`)},
+					DependsOn:  []string{"database"},
+				},
+			}, {
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "frontend",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"frontend"}`)},
+					DependsOn:  []string{"backend"},
+				},
+			}},
+		},
+		"component-without-dependency": {
+			input: []workflowv1alpha1.WorkflowStep{},
+			app: &v1beta1.Application{
+				Spec: v1beta1.ApplicationSpec{
+					Components: []common.ApplicationComponent{{
+						Name: "standalone",
+						Type: "webservice",
+					}},
+				},
+			},
+			output: []workflowv1alpha1.WorkflowStep{{
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "standalone",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"standalone"}`)},
+				},
+			}},
+		},
+		"mixed-components-some-with-dependencies": {
+			input: []workflowv1alpha1.WorkflowStep{},
+			app: &v1beta1.Application{
+				Spec: v1beta1.ApplicationSpec{
+					Components: []common.ApplicationComponent{{
+						Name: "independent1",
+						Type: "webservice",
+					}, {
+						Name: "database",
+						Type: "webservice",
+					}, {
+						Name:      "dependent1",
+						Type:      "webservice",
+						DependsOn: []string{"database"},
+					}, {
+						Name: "independent2",
+						Type: "webservice",
+					}},
+				},
+			},
+			output: []workflowv1alpha1.WorkflowStep{{
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "independent1",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"independent1"}`)},
+				},
+			}, {
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "database",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"database"}`)},
+				},
+			}, {
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "dependent1",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"dependent1"}`)},
+					DependsOn:  []string{"database"},
+				},
+			}, {
+				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
+					Name:       "independent2",
+					Type:       "apply-component",
+					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"independent2"}`)},
+				},
+			}},
+		},
+	}
+
+	generator := &ApplyComponentWorkflowStepGenerator{}
+
+	for name, testCase := range testCases {
+		t.Run(name, func(t *testing.T) {
+			output, err := generator.Generate(testCase.app, testCase.input)
+			if testCase.hasError {
+				r.Error(err)
+			} else {
+				r.NoError(err)
+				r.Equal(testCase.output, output)
+			}
+		})
+	}
+}
+
+func TestComponentDependsOnFieldPreservation(t *testing.T) {
+	r := require.New(t)
+
+	// This test specifically verifies that the DependsOn field from components
+	// is correctly carried forward to workflow steps, enabling execution gating
+	app := &v1beta1.Application{
+		Spec: v1beta1.ApplicationSpec{
+			Components: []common.ApplicationComponent{{
+				Name: "database",
+				Type: "webservice",
+			}, {
+				Name:      "api-server",
+				Type:      "webservice",
+				DependsOn: []string{"database"},
+			}, {
+				Name:      "worker",
+				Type:      "webservice",
+				DependsOn: []string{"database", "api-server"},
+			}},
+		},
+	}
+
+	generator := &ApplyComponentWorkflowStepGenerator{}
+	output, err := generator.Generate(app, []workflowv1alpha1.WorkflowStep{})
+
+	r.NoError(err)
+	r.Len(output, 3)
+
+	// Verify the database component has no dependencies
+	r.Equal("database", output[0].Name)
+	r.Nil(output[0].DependsOn)
+
+	// Verify api-server has database dependency
+	r.Equal("api-server", output[1].Name)
+	r.Equal([]string{"database"}, output[1].DependsOn)
+
+	// Verify worker has both dependencies
+	r.Equal("worker", output[2].Name)
+	r.Equal([]string{"database", "api-server"}, output[2].DependsOn)
+}
+
+func TestChainGeneratorWithComponentDependsOn(t *testing.T) {
+	r := require.New(t)
+
+	// Test that the chain generator preserves component dependencies
+	cli := fake.NewClientBuilder().WithScheme(common2.Scheme).Build()
+
+	app := &v1beta1.Application{
+		Spec: v1beta1.ApplicationSpec{
+			Components: []common.ApplicationComponent{{
+				Name: "database",
+				Type: "webservice",
+			}, {
+				Name:      "backend",
+				Type:      "webservice",
+				DependsOn: []string{"database"},
+			}},
+		},
+	}
+
+	generator := NewChainWorkflowStepGenerator(
+		&RefWorkflowStepGenerator{Context: context.Background(), Client: cli},
+		&DeployWorkflowStepGenerator{},
+		&Deploy2EnvWorkflowStepGenerator{},
+		&ApplyComponentWorkflowStepGenerator{},
+	)
+
+	output, err := generator.Generate(app, []workflowv1alpha1.WorkflowStep{})
+	r.NoError(err)
+	r.Len(output, 2)
+
+	// Find the backend step and verify it has the dependency
+	var backendStep *workflowv1alpha1.WorkflowStep
+	for i, step := range output {
+		if step.Name == "backend" {
+			backendStep = &output[i]
+			break
+		}
+	}
+
+	r.NotNil(backendStep, "Backend step should exist")
+	r.Equal([]string{"database"}, backendStep.DependsOn, "Backend step should depend on database")
+}
+
 func TestIsBuiltinWorkflowStepType(t *testing.T) {
 	assert.True(t, IsBuiltinWorkflowStepType("suspend"))
 	assert.True(t, IsBuiltinWorkflowStepType("apply-component"))
diff --git a/test/e2e-multicluster-test/multicluster_standalone_test.go b/test/e2e-multicluster-test/multicluster_standalone_test.go
index 903c331f..882a827a 100644
--- a/test/e2e-multicluster-test/multicluster_standalone_test.go
+++ b/test/e2e-multicluster-test/multicluster_standalone_test.go
@@ -22,6 +22,7 @@ import (
 	"os"
 	"time"
 
+	workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
 	v1 "k8s.io/api/apps/v1"
@@ -35,8 +36,6 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/yaml"
 
-	workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
-
 	oamcomm "github.com/oam-dev/kubevela/apis/core.oam.dev/common"
 	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
 	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
@@ -215,7 +214,7 @@ var _ = Describe("Test multicluster standalone scenario", func() {
 		Eventually(func(g Gomega) {
 			g.Expect(k8sClient.Get(hubCtx, appKey, app)).Should(Succeed())
 			g.Expect(app.Status.Phase).Should(Equal(oamcomm.ApplicationRunning))
-		}, 30*time.Second).Should(Succeed())
+		}, 2*time.Minute).Should(Succeed())
 
 		By("Update Application to first failed version")
 		Eventually(func(g Gomega) {
@@ -223,12 +222,12 @@ var _ = Describe("Test multicluster standalone scenario", func() {
 			app.Annotations[oam.AnnotationPublishVersion] = "alpha2"
 			app.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(`{"image":"busybox:bad"}`)}
 			g.Expect(k8sClient.Update(hubCtx, app)).Should(Succeed())
-		}, 30*time.Second).Should(Succeed())
+		}, 2*time.Minute).Should(Succeed())
 
 		Eventually(func(g Gomega) {
 			g.Expect(k8sClient.Get(hubCtx, appKey, app)).Should(Succeed())
 			g.Expect(app.Status.Phase).Should(Equal(oamcomm.ApplicationRunningWorkflow))
-		}, 30*time.Second).Should(Succeed())
+		}, 2*time.Minute).Should(Succeed())
 
 		By("Update Application to second failed version")
 		Eventually(func(g Gomega) {
@@ -236,12 +235,12 @@ var _ = Describe("Test multicluster standalone scenario", func() {
 			app.Annotations[oam.AnnotationPublishVersion] = "alpha3"
 			app.Spec.Components[0].Name = "busybox-bad"
 			g.Expect(k8sClient.Update(hubCtx, app)).Should(Succeed())
-		}, 30*time.Second).Should(Succeed())
+		}, 2*time.Minute).Should(Succeed())
 		Eventually(func(g Gomega) {
 			deploy := &v1.Deployment{}
 			g.Expect(k8sClient.Get(workerCtx, types.NamespacedName{Namespace: namespace, Name: "busybox"}, deploy)).Should(Succeed())
 			g.Expect(k8sClient.Delete(workerCtx, deploy)).Should(Succeed())
-		}, 30*time.Second).Should(Succeed())
+		}, 2*time.Minute).Should(Succeed())
 
 		By("Change external policy")
 		Eventually(func(g Gomega) {
@@ -250,7 +249,7 @@ var _ = Describe("Test multicluster standalone scenario", func() {
 			g.Expect(k8sClient.Get(hubCtx, types.NamespacedName{Namespace: namespace, Name: "topology-worker"}, policy)).Should(Succeed())
 			policy.Properties = &runtime.RawExtension{Raw: []byte(`{"clusters":["changed"]}`)}
 			g.Expect(k8sClient.Update(hubCtx, policy)).Should(Succeed())
-		}, 30*time.Second).Should(Succeed())
+		}, 2*time.Minute).Should(Succeed())
 
 		By("Change referred objects")
 		Eventually(func(g Gomega) {
@@ -258,7 +257,7 @@ var _ = Describe("Test multicluster standalone scenario", func() {
 			g.Expect(k8sClient.Get(hubCtx, types.NamespacedName{Namespace: namespace, Name: "busybox-ref"}, deploy)).Should(Succeed())
 			deploy.Spec.Replicas = ptr.To(int32(1))
 			g.Expect(k8sClient.Update(hubCtx, deploy)).Should(Succeed())
-		}, 30*time.Second).Should(Succeed())
+		}, 2*time.Minute).Should(Succeed())
 
 		By("Live-diff application")
 		outputs, err := execCommand("live-diff", "-r", "busybox-v3,busybox-v1", "-n", namespace)
diff --git a/test/e2e-test/application_test.go b/test/e2e-test/application_test.go
index e5707ae3..bb1e3c16 100644
--- a/test/e2e-test/application_test.go
+++ b/test/e2e-test/application_test.go
@@ -25,6 +25,7 @@ import (
 
 	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/cuecontext"
+	workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
 
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
@@ -539,3 +540,196 @@ var _ = Describe("Application Normal tests", func() {
 		Expect(app.Status.Services[0].Traits[0].Details["allReplicasReady"]).Should(Equal("true"))
 	})
 })
+
+var _ = Describe("Test Component Level DependsOn", func() {
+	ctx := context.TODO()
+	namespaceName := "component-depends-on-test"
+
+	BeforeEach(func() {
+		By("Creating namespace for component dependsOn tests")
+		createNamespace(ctx, namespaceName)
+	})
+
+	AfterEach(func() {
+		By("Cleaning up resources after each test")
+		// Clean up applications
+		appList := &v1beta1.ApplicationList{}
+		Expect(k8sClient.List(ctx, appList, client.InNamespace(namespaceName))).Should(BeNil())
+		for _, app := range appList.Items {
+			Expect(k8sClient.Delete(ctx, &app)).Should(BeNil())
+		}
+		// Wait for applications to be deleted
+		Eventually(func() bool {
+			appList := &v1beta1.ApplicationList{}
+			_ = k8sClient.List(ctx, appList, client.InNamespace(namespaceName))
+			return len(appList.Items) == 0
+		}, 120*time.Second, 2*time.Second).Should(BeTrue())
+	})
+
+	It("Component dependsOn should enforce execution gating - success scenario", func() {
+		By("Apply an application with chained component dependencies")
+		var app v1beta1.Application
+		applyApp(ctx, namespaceName, "app_component_depends_on_success.yaml", &app)
+
+		By("Verify application reaches running state")
+		verifyApplicationPhase(ctx, namespaceName, "app-component-depends-on-success", oamcomm.ApplicationRunning)
+
+		By("Verify all components are healthy")
+		Eventually(func() bool {
+			var testApp v1beta1.Application
+			err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: "app-component-depends-on-success"}, &testApp)
+			if err != nil {
+				return false
+			}
+
+			if len(testApp.Status.Services) != 3 {
+				return false
+			}
+
+			// Check if all components are healthy
+			for _, service := range testApp.Status.Services {
+				if !service.Healthy {
+					return false
+				}
+			}
+			return true
+		}, 180*time.Second, 5*time.Second).Should(BeTrue())
+
+		By("Verify workflow execution order through step status")
+		var testApp v1beta1.Application
+		Expect(k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: "app-component-depends-on-success"}, &testApp)).Should(BeNil())
+
+		// Verify workflow steps were executed in correct order
+		if testApp.Status.Workflow != nil {
+			stepStatus := testApp.Status.Workflow.Steps
+			databaseStepFound := false
+			backendStepFound := false
+			frontendStepFound := false
+
+			for _, step := range stepStatus {
+				switch step.Name {
+				case "database":
+					Expect(step.Phase).Should(Equal(workflowv1alpha1.WorkflowStepPhaseSucceeded))
+					databaseStepFound = true
+				case "backend":
+					// Backend should only succeed after database
+					Expect(step.Phase).Should(Equal(workflowv1alpha1.WorkflowStepPhaseSucceeded))
+					Expect(databaseStepFound).Should(BeTrue()) // Database should be processed first
+					backendStepFound = true
+				case "frontend":
+					// Frontend should only succeed after backend
+					Expect(step.Phase).Should(Equal(workflowv1alpha1.WorkflowStepPhaseSucceeded))
+					Expect(backendStepFound).Should(BeTrue()) // Backend should be processed before frontend
+					frontendStepFound = true
+				}
+			}
+			Expect(databaseStepFound && backendStepFound && frontendStepFound).Should(BeTrue())
+		}
+	})
+
+	It("Component dependsOn should block dependent components when dependency fails", func() {
+		By("Apply an application where the first component will fail")
+		var app v1beta1.Application
+		applyApp(ctx, namespaceName, "app_component_depends_on_fail.yaml", &app)
+
+		By("Wait for the application to process")
+		time.Sleep(30 * time.Second)
+
+		By("Verify the failing component is unhealthy and dependent component is not provisioned")
+		Eventually(func() bool {
+			var testApp v1beta1.Application
+			err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: "app-component-depends-on-fail"}, &testApp)
+			if err != nil {
+				return false
+			}
+
+			// Check workflow status to ensure dependent step is suspended/waiting
+			if testApp.Status.Workflow != nil {
+				stepStatus := testApp.Status.Workflow.Steps
+				failingStepFound := false
+				dependentStepBlocked := true
+
+				for _, step := range stepStatus {
+					switch step.Name {
+					case "failing-database":
+						// The failing component should be in failed state or retrying
+						if step.Phase == workflowv1alpha1.WorkflowStepPhaseFailed {
+							failingStepFound = true
+						}
+					case "dependent-backend":
+						// The dependent component should be suspended/pending due to dependency failure
+						if step.Phase == workflowv1alpha1.WorkflowStepPhaseSucceeded {
+							dependentStepBlocked = false
+						}
+					}
+				}
+				return failingStepFound && dependentStepBlocked
+			}
+			return false
+		}, 120*time.Second, 5*time.Second).Should(BeTrue())
+
+		By("Verify application is not in running state due to component failure")
+		var testApp v1beta1.Application
+		Expect(k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: "app-component-depends-on-fail"}, &testApp)).Should(BeNil())
+		Expect(testApp.Status.Phase).ShouldNot(Equal(oamcomm.ApplicationRunning))
+	})
+
+	It("Component dependsOn should work with multiple dependencies", func() {
+		By("Apply an application with component having multiple dependencies")
+		var app v1beta1.Application
+		applyApp(ctx, namespaceName, "app_component_depends_on_multiple.yaml", &app)
+
+		By("Verify application reaches running state")
+		verifyApplicationPhase(ctx, namespaceName, "app-component-depends-on-multiple", oamcomm.ApplicationRunning)
+
+		By("Verify all components are healthy")
+		Eventually(func() bool {
+			var testApp v1beta1.Application
+			err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: "app-component-depends-on-multiple"}, &testApp)
+			if err != nil {
+				return false
+			}
+
+			if len(testApp.Status.Services) != 3 {
+				return false
+			}
+
+			// Check if all components are healthy
+			for _, service := range testApp.Status.Services {
+				if !service.Healthy {
+					return false
+				}
+			}
+			return true
+		}, 180*time.Second, 5*time.Second).Should(BeTrue())
+
+		By("Verify workflow execution dependencies")
+		var testApp v1beta1.Application
+		Expect(k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: "app-component-depends-on-multiple"}, &testApp)).Should(BeNil())
+
+		// Verify workflow steps were executed with proper dependencies
+		if testApp.Status.Workflow != nil {
+			stepStatus := testApp.Status.Workflow.Steps
+			databaseStepSucceeded := false
+			cacheStepSucceeded := false
+			backendStepSucceeded := false
+
+			for _, step := range stepStatus {
+				switch step.Name {
+				case "database":
+					Expect(step.Phase).Should(Equal(workflowv1alpha1.WorkflowStepPhaseSucceeded))
+					databaseStepSucceeded = true
+				case "cache":
+					Expect(step.Phase).Should(Equal(workflowv1alpha1.WorkflowStepPhaseSucceeded))
+					cacheStepSucceeded = true
+				case "backend":
+					// Backend should only succeed after both database and cache
+					Expect(step.Phase).Should(Equal(workflowv1alpha1.WorkflowStepPhaseSucceeded))
+					Expect(databaseStepSucceeded && cacheStepSucceeded).Should(BeTrue())
+					backendStepSucceeded = true
+				}
+			}
+			Expect(databaseStepSucceeded && cacheStepSucceeded && backendStepSucceeded).Should(BeTrue())
+		}
+	})
+})
diff --git a/test/e2e-test/definition_test.go b/test/e2e-test/definition_test.go
index 692a7e8c..c0e58401 100644
--- a/test/e2e-test/definition_test.go
+++ b/test/e2e-test/definition_test.go
@@ -29,11 +29,14 @@ import (
 	. "github.com/onsi/gomega"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	pkgruntime "k8s.io/apimachinery/pkg/runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
 	"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
 	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
 	"github.com/oam-dev/kubevela/apis/types"
+	pkgdef "github.com/oam-dev/kubevela/pkg/definition"
 	"github.com/oam-dev/kubevela/pkg/oam"
 	"github.com/oam-dev/kubevela/pkg/oam/util"
 	utilcommon "github.com/oam-dev/kubevela/pkg/utils/common"
@@ -260,4 +263,90 @@ var _ = Describe("ComponentDefinition Normal tests", func() {
 		By("Verify application is running")
 		verifyApplicationPhase(context.TODO(), newApp.Namespace, newApp.Name, common.ApplicationRunning)
 	})
+
+	Context("Definition Retrieval and CUE Parsing Validation", func() {
+		It("should successfully parse all definitions loaded from helm chart templates", func() {
+			By("Loading all definition YAML files from charts/vela-core/templates/defwithtemplate")
+			_, file, _, _ := runtime.Caller(0)
+			definitionDir := filepath.Join(file, "../../../charts/vela-core/templates/defwithtemplate")
+
+			files, err := filepath.Glob(filepath.Join(definitionDir, "*.yaml"))
+			Expect(err).To(BeNil())
+			Expect(len(files)).To(BeNumerically(">", 0))
+
+			By(fmt.Sprintf("Found %d definition YAML files to test", len(files)))
+
+			// Install all definitions
+			installedDefinitions := []string{}
+			for _, definitionFile := range files {
+				definitionName := strings.TrimSuffix(filepath.Base(definitionFile), ".yaml")
+				By(fmt.Sprintf("Installing definition from %s", definitionName))
+
+				err := testdef.InstallDefinitionFromYAML(ctx, k8sClient, definitionFile, func(s string) string {
+					// Replace helm template placeholders like the existing notification test
+					s = strings.ReplaceAll(s, `{{ include "systemDefinitionNamespace" . }}`, namespace)
+					s = strings.ReplaceAll(s, `{{- include "systemDefinitionNamespace" . }}`, namespace)
+					return s
+				})
+				if err != nil {
+					// Some definitions might fail to install due to dependencies, that's ok
+					fmt.Printf("Warning: Failed to install definition from %s: %v\n", definitionFile, err)
+				} else {
+					installedDefinitions = append(installedDefinitions, definitionName)
+				}
+			}
+
+			By(fmt.Sprintf("Successfully installed %d definitions, now testing CUE parsing", len(installedDefinitions)))
+
+			// Test CUE parsing on all installed ComponentDefinitions
+			By("Testing CUE parsing for ComponentDefinitions")
+			var componentDefs v1beta1.ComponentDefinitionList
+			Expect(k8sClient.List(ctx, &componentDefs, &client.ListOptions{Namespace: namespace})).Should(Succeed())
+
+			componentErrorCount := 0
+			for i := range componentDefs.Items {
+				unstructuredObj, err := pkgruntime.DefaultUnstructuredConverter.ToUnstructured(&componentDefs.Items[i])
+				if err != nil {
+					componentErrorCount++
+					fmt.Printf("ERROR: ComponentDefinition %s failed to convert to unstructured: %v\n", componentDefs.Items[i].Name, err)
+					continue
+				}
+
+				def := &pkgdef.Definition{Unstructured: unstructured.Unstructured{Object: unstructuredObj}}
+				_, err = def.ToCUEString()
+				if err != nil {
+					componentErrorCount++
+					fmt.Printf("ERROR: ComponentDefinition %s failed CUE parsing: %v\n", componentDefs.Items[i].Name, err)
+				}
+			}
+
+			// Test CUE parsing on all installed TraitDefinitions
+			By("Testing CUE parsing for TraitDefinitions")
+			var traitDefs v1beta1.TraitDefinitionList
+			Expect(k8sClient.List(ctx, &traitDefs, &client.ListOptions{Namespace: namespace})).Should(Succeed())
+
+			traitErrorCount := 0
+			for i := range traitDefs.Items {
+				unstructuredObj, err := pkgruntime.DefaultUnstructuredConverter.ToUnstructured(&traitDefs.Items[i])
+				if err != nil {
+					traitErrorCount++
+					fmt.Printf("ERROR: TraitDefinition %s failed to convert to unstructured: %v\n", traitDefs.Items[i].Name, err)
+					continue
+				}
+
+				def := &pkgdef.Definition{Unstructured: unstructured.Unstructured{Object: unstructuredObj}}
+				_, err = def.ToCUEString()
+				if err != nil {
+					traitErrorCount++
+					fmt.Printf("ERROR: TraitDefinition %s failed CUE parsing: %v\n", traitDefs.Items[i].Name, err)
+				}
+			}
+
+			By(fmt.Sprintf("CUE parsing results: %d ComponentDefinitions tested, %d TraitDefinitions tested",
+				len(componentDefs.Items), len(traitDefs.Items)))
+
+			totalErrors := componentErrorCount + traitErrorCount
+			Expect(totalErrors).To(Equal(0), fmt.Sprintf("%d definitions failed CUE parsing with updated logic", totalErrors))
+		})
+	})
 })
diff --git a/test/e2e-test/testdata/app/app_component_depends_on_fail.yaml b/test/e2e-test/testdata/app/app_component_depends_on_fail.yaml
new file mode 100644
index 00000000..65bf39d8
--- /dev/null
+++ b/test/e2e-test/testdata/app/app_component_depends_on_fail.yaml
@@ -0,0 +1,22 @@
+apiVersion: core.oam.dev/v1beta1
+kind: Application
+metadata:
+  name: app-component-depends-on-fail
+spec:
+  components:
+    - name: failing-database
+      type: webservice
+      properties:
+        image: ""  # This will fail to pull
+        ports:
+          - port: 3306
+            expose: false
+    - name: dependent-backend
+      type: webservice
+      dependsOn:
+        - failing-database
+      properties:
+        image: "nginx:1.20"
+        ports:
+          - port: 8080
+            expose: false
diff --git a/test/e2e-test/testdata/app/app_component_depends_on_multiple.yaml b/test/e2e-test/testdata/app/app_component_depends_on_multiple.yaml
new file mode 100644
index 00000000..a9d2618f
--- /dev/null
+++ b/test/e2e-test/testdata/app/app_component_depends_on_multiple.yaml
@@ -0,0 +1,30 @@
+apiVersion: core.oam.dev/v1beta1
+kind: Application
+metadata:
+  name: app-component-depends-on-multiple
+spec:
+  components:
+    - name: database
+      type: webservice
+      properties:
+        image: "nginx:1.20"
+        ports:
+          - port: 3306
+            expose: false
+    - name: cache
+      type: webservice
+      properties:
+        image: "nginx:1.20"
+        ports:
+          - port: 6379
+            expose: false
+    - name: backend
+      type: webservice
+      dependsOn:
+        - database
+        - cache
+      properties:
+        image: "nginx:1.20"
+        ports:
+          - port: 8080
+            expose: false
diff --git a/test/e2e-test/testdata/app/app_component_depends_on_success.yaml b/test/e2e-test/testdata/app/app_component_depends_on_success.yaml
new file mode 100644
index 00000000..07aa809a
--- /dev/null
+++ b/test/e2e-test/testdata/app/app_component_depends_on_success.yaml
@@ -0,0 +1,31 @@
+apiVersion: core.oam.dev/v1beta1
+kind: Application
+metadata:
+  name: app-component-depends-on-success
+spec:
+  components:
+    - name: database
+      type: webservice
+      properties:
+        image: "nginx:1.20"
+        ports:
+          - port: 3306
+            expose: false
+    - name: backend
+      type: webservice
+      dependsOn:
+        - database
+      properties:
+        image: "nginx:1.20"
+        ports:
+          - port: 8080
+            expose: false
+    - name: frontend
+      type: webservice
+      dependsOn:
+        - backend
+      properties:
+        image: "nginx:1.20"
+        ports:
+          - port: 80
+            expose: true