From 8ceb1f1b890a20091ba9394f073d4fedd6d69d0e Mon Sep 17 00:00:00 2001 From: bharat941 Date: Thu, 13 Aug 2026 15:41:18 +0530 Subject: [PATCH] feat(aem/cloud-service): add vault-package-dependencies code-assessment pattern - Add VaultPackageDependencies detector (pom-only, mechanical fix) - Add expert skill SKILL.md + recipe.md under code-assessment/ - Register detector in Registry.java - Add routing hint to code-assessment/SKILL.md - Add catalog row (high severity, ready, analyzer, mechanical) to patterns.md - Add vault deploy blocker entry to migration/SKILL.md - Add positive + negative test fixtures - Add test cases to run-tests.sh - Remove duplicate standalone skills/vault-package-dependencies/ skill --- .../skills/code-assessment/SKILL.md | 1 + .../code-assessment/references/patterns.md | 1 + .../scripts/analyzer/Registry.java | 4 +- .../detectors/VaultPackageDependencies.java | 89 +++++++++++++++++++ .../vault-package-dependencies/SKILL.md | 71 +++++++++++++++ .../vault-package-dependencies/recipe.md | 86 ++++++++++++++++++ .../cloud-service/skills/migration/SKILL.md | 1 + .../vault-package-dependencies-clean/pom.xml | 23 +++++ .../vault-package-dependencies/pom.xml | 39 ++++++++ .../test/code-assessment/run-tests.sh | 9 ++ 10 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 plugins/aem/cloud-service/skills/code-assessment/scripts/analyzer/detectors/VaultPackageDependencies.java create mode 100644 plugins/aem/cloud-service/skills/code-assessment/vault-package-dependencies/SKILL.md create mode 100644 plugins/aem/cloud-service/skills/code-assessment/vault-package-dependencies/recipe.md create mode 100644 plugins/aem/cloud-service/test/code-assessment/fixtures/vault-package-dependencies-clean/pom.xml create mode 100644 plugins/aem/cloud-service/test/code-assessment/fixtures/vault-package-dependencies/pom.xml diff --git a/plugins/aem/cloud-service/skills/code-assessment/SKILL.md b/plugins/aem/cloud-service/skills/code-assessment/SKILL.md index 020dbb6f..c2a35be3 100644 --- a/plugins/aem/cloud-service/skills/code-assessment/SKILL.md +++ b/plugins/aem/cloud-service/skills/code-assessment/SKILL.md @@ -52,6 +52,7 @@ Route the request to one expert skill. Two pattern families share this skill: | User said / saw | Expert skill | |---|---| | "update aem sdk", "upgrade mockito", stale `` or `${property}` in pom | [`outdated-dependencies/`](outdated-dependencies/SKILL.md) | +| "package install fails on AEMaaCS", `day/cq60/product`, "CRX refuses install", Vault dependency not found at deploy time | [`vault-package-dependencies/`](vault-package-dependencies/SKILL.md) | | "fix @Inject", "modernize Sling Models", `javax.inject.Inject` on `@Model` fields | [`inject-in-sling-model/`](inject-in-sling-model/SKILL.md) | | "add HTTP timeouts", "outbound/external call has no timeout", `HttpClient` / `HttpClients` / `OkHttpClient` built without a timeout | [`outbound-call-timeouts/`](outbound-call-timeouts/SKILL.md) | | "bound my query", "unbounded query", "query causing OOM", `p.limit=-1`, `setLimit(-1)` | [`unbounded-query/`](unbounded-query/SKILL.md) | diff --git a/plugins/aem/cloud-service/skills/code-assessment/references/patterns.md b/plugins/aem/cloud-service/skills/code-assessment/references/patterns.md index 2ca9a413..a4b14c2c 100644 --- a/plugins/aem/cloud-service/skills/code-assessment/references/patterns.md +++ b/plugins/aem/cloud-service/skills/code-assessment/references/patterns.md @@ -46,6 +46,7 @@ Adding a pattern: add a row here, then build the expert skill from | `unbounded-recursion` | add a depth guard to self-recursive / tree-traversal methods (incl. navigation & breadcrumb) | medium | planned | - | - | | `unbounded-graphql` | add pagination (`first` / `limit`) to GraphQL queries | medium | planned | - | - | | `logging-in-loops` | move logging out of hot loops / add level guards | low | planned | - | - | +| [`vault-package-dependencies`](../vault-package-dependencies/SKILL.md) | remove AEM 6.x Vault install-time package dependencies (`day/cq60/product:*`) from `content-package-maven-plugin` that block installation on AEMaaCS | high | ready | analyzer | mechanical | | [`remove-deprecated-api`](../remove-deprecated-api/SKILL.md) | migrate deprecated and removed Java APIs to comply with AEM as a Cloud Service enforcement | high | ready | analyzer | guided | > Out-of-memory / leak incidents — a frequent symptom — are usually caused by diff --git a/plugins/aem/cloud-service/skills/code-assessment/scripts/analyzer/Registry.java b/plugins/aem/cloud-service/skills/code-assessment/scripts/analyzer/Registry.java index 4fe1f7eb..3749baf1 100644 --- a/plugins/aem/cloud-service/skills/code-assessment/scripts/analyzer/Registry.java +++ b/plugins/aem/cloud-service/skills/code-assessment/scripts/analyzer/Registry.java @@ -10,6 +10,7 @@ import analyzer.detectors.ResourceChangeListener; import analyzer.detectors.Scheduler; import analyzer.detectors.UnboundedQuery; +import analyzer.detectors.VaultPackageDependencies; import java.util.ArrayList; import java.util.Arrays; @@ -28,7 +29,8 @@ public static List all() { new AssetManager(), new OutboundCallTimeouts(), new UnboundedQuery(), - new RemoveDeprecatedApi() + new RemoveDeprecatedApi(), + new VaultPackageDependencies() )); } } diff --git a/plugins/aem/cloud-service/skills/code-assessment/scripts/analyzer/detectors/VaultPackageDependencies.java b/plugins/aem/cloud-service/skills/code-assessment/scripts/analyzer/detectors/VaultPackageDependencies.java new file mode 100644 index 00000000..64cb3154 --- /dev/null +++ b/plugins/aem/cloud-service/skills/code-assessment/scripts/analyzer/detectors/VaultPackageDependencies.java @@ -0,0 +1,89 @@ +package analyzer.detectors; + +import analyzer.Corpus; +import analyzer.Detector; +import analyzer.Finding; +import analyzer.PomUnit; +import analyzer.util.Poms; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Detects AEM 6.x product-package Vault install-time {@code } declared inside + * {@code content-package-maven-plugin / } that cannot be resolved on AEM as a + * Cloud Service. The product packages (day/cq60/product, day/cq560/*, adobe/cq60) are baked + * into the AEMaaCS container image and are not present in CRX Package Manager — so CRX refuses + * to install the customer package at deploy time even though {@code mvn clean install} succeeds. + * + *

Emits one finding per {@code } block (not per {@code } entry) + * because the fix removes the entire block. + */ +public final class VaultPackageDependencies implements Detector { + + public String pattern() { return "vault-package-dependencies"; } + public boolean needsJava() { return false; } // pom-only detector + + /** Group-path prefixes whose packages don't exist on AEMaaCS. */ + private static final String[] LEGACY_PREFIXES = { + "day/cq60/", + "day/cq560/", + "adobe/cq60", + }; + + private static boolean isLegacyGroup(String group) { + if (group == null) return false; + for (String p : LEGACY_PREFIXES) { + if (group.startsWith(p) || group.equals(p.replaceAll("/$", ""))) return true; + } + return false; + } + + public void detect(Corpus c, List out, List warnings) { + for (PomUnit pom : c.poms) { + Map cursor = new HashMap<>(); + NodeList plugins = pom.doc.getElementsByTagName("plugin"); + for (int i = 0; i < plugins.getLength(); i++) { + Element plugin = (Element) plugins.item(i); + String artifactId = Poms.childText(plugin, "artifactId"); + if (!"content-package-maven-plugin".equals(artifactId)) continue; + + // Find direct children of this plugin + NodeList pluginChildren = plugin.getChildNodes(); + for (int j = 0; j < pluginChildren.getLength(); j++) { + Node pch = pluginChildren.item(j); + if (pch.getNodeType() != Node.ELEMENT_NODE) continue; + if (!"configuration".equals(pch.getNodeName())) continue; + Element config = (Element) pch; + + // Find direct children of configuration + NodeList configChildren = config.getChildNodes(); + for (int k = 0; k < configChildren.getLength(); k++) { + Node cch = configChildren.item(k); + if (cch.getNodeType() != Node.ELEMENT_NODE) continue; + if (!"dependencies".equals(cch.getNodeName())) continue; + Element depList = (Element) cch; + + // Emit one finding if any carries a legacy + NodeList deps = depList.getElementsByTagName("dependency"); + for (int m = 0; m < deps.getLength(); m++) { + String group = Poms.childText((Element) deps.item(m), "group"); + if (isLegacyGroup(group)) { + long ln = Poms.findLine(pom.lines, + "content-package-maven-plugin", + cursor); + out.add(new Finding(pattern(), pom.rel, ln, + "content-package-maven-plugin: legacy Vault dependency group=" + group)); + break; // one finding per block + } + } + } + } + } + } + } +} diff --git a/plugins/aem/cloud-service/skills/code-assessment/vault-package-dependencies/SKILL.md b/plugins/aem/cloud-service/skills/code-assessment/vault-package-dependencies/SKILL.md new file mode 100644 index 00000000..8581b7fd --- /dev/null +++ b/plugins/aem/cloud-service/skills/code-assessment/vault-package-dependencies/SKILL.md @@ -0,0 +1,71 @@ +--- +name: vault-package-dependencies +description: | + AEM Cloud Service expert skill — remove legacy AEM 6.x Vault install-time from + content-package-maven-plugin in pom.xml. These day/cq60/product:* entries do not + exist on AEMaaCS (the platform is baked into the container image), so CRX Package Manager refuses + to install the package at deploy time even though the Maven build succeeds. Use for "package install + fails on AEMaaCS", "day/cq60/product dependency", "CRX refuses install", or when scanning a project + for deployment blockers. Fix is mechanical: remove the entire block. +license: Apache-2.0 +--- + +# Vault package dependencies — AEM as a Cloud Service + +> This pattern is executed by the code-assessment runbook — follow [`../references/runbook.md`](../references/runbook.md) for the full flow (preflight → plan → apply → verify, run log). This skill supplies the detection + recipe the runbook applies. + +## Overview + +Content packages built for AEM 6.x declare Vault install-time `` inside +`content-package-maven-plugin / `. These reference AEM 6.x product packages +(`day/cq60/product:cq-content`, `day/cq60/product:cq-commerce-content`, etc.) that were +pre-installed on AEM 6.x instances. On AEM as a Cloud Service the platform is delivered via a +container image — those product packages no longer exist as installable entries in CRX Package +Manager. CRX Package Manager checks all declared Vault dependencies at install time and **refuses +the install** if any are unresolvable, even though `mvn clean install` succeeds. + +The fix is mechanical: remove the entire `` block. The functionality the packages +provided is still present on AEMaaCS; only the install-time check needs to be removed. + +## Classification — confirm this pattern applies + +- A `pom.xml` whose `content-package-maven-plugin / ` contains a `` + block with at least one `` whose `` starts with `day/cq60/`, `day/cq560/`, + or `adobe/cq60`. +- Applies regardless of whether the plugin groupId is `com.day.jcr.vault` (legacy) or + `org.apache.jackrabbit` (current filevault-package-maven-plugin). +- The same pom may have the plugin in both main `` and inside `` — check both. + +## Discovery + +Detection is performed by the analyzer ([`../scripts/analyze.sh`](../scripts/README.md)), run by +the runbook: + +```bash +bash ../scripts/analyze.sh --pattern vault-package-dependencies +``` + +**Match criteria:** a `` whose direct `` child equals +`content-package-maven-plugin`, with a direct `` child containing a direct +`` child that has at least one `/` prefixed with `day/cq60/`, +`day/cq560/`, or `adobe/cq60`. One finding per `` block. + +## Resolution contract + +**self-evident** — always remove the entire `` block. No user input required. + +## Review checklist + +- [ ] Only the `` block under `content-package-maven-plugin / ` removed — no other plugin config touched +- [ ] Maven classpath `` at the project level left intact +- [ ] No whitespace churn outside the removed block +- [ ] All occurrences removed — check both main `` and any `` sections +- [ ] Build still succeeds after the change (`mvn clean install`) + +## Recipe + +Read [`recipe.md`](recipe.md) in full before editing: locator, edit, unlocatable reasons, before/after example, editing strategy. + +## Handoff + +The skill never commits. See [`../references/git-workflow.md`](../references/git-workflow.md) for git vs in-place handoff and the suggested commit message. diff --git a/plugins/aem/cloud-service/skills/code-assessment/vault-package-dependencies/recipe.md b/plugins/aem/cloud-service/skills/code-assessment/vault-package-dependencies/recipe.md new file mode 100644 index 00000000..0ec18045 --- /dev/null +++ b/plugins/aem/cloud-service/skills/code-assessment/vault-package-dependencies/recipe.md @@ -0,0 +1,86 @@ +# Recipe — Vault package dependencies + +> Read this fully before editing. Control plane: [SKILL.md](SKILL.md). + +## Input contract + +Per invocation, a deduplicated list of repo-relative pom paths: + +```json +{ + "files": [ + "ui.apps/pom.xml", + "ui.commons/pom.xml" + ] +} +``` + +Sources: + +1. **User-named** — the user names the pom file(s) directly. +2. **Discover** — the file list is the output of the **Discovery** scan in [`SKILL.md`](SKILL.md). + +## Locator + +For each file: + +1. Find the `` element whose direct `` child text equals `content-package-maven-plugin`. +2. Inside that plugin, find the direct `` child element. +3. Inside ``, find the direct `` child element containing at least one `/` prefixed with `day/cq60/`, `day/cq560/`, or `adobe/cq60`. +4. Repeat for every occurrence of `content-package-maven-plugin` in the file — the same pom may declare the plugin in the main `` section **and** in one or more `//` sections. + +## Edit + +Remove the entire `...` block, including its surrounding blank/indentation line. Do not touch any sibling elements (``, ``, ``, ``, etc.). + +## Before / after + +**Before (`ui.apps/pom.xml`):** +```xml + + true + true + adobe/aem6/sample + true + + + day/cq60/product + cq-content + [6.3.0,) + + + day/cq60/product + cq-commerce-content + [1.5.0,) + + + + ... + + +``` + +**After:** +```xml + + true + true + adobe/aem6/sample + true + + ... + + +``` + +## Unlocatable / skip reasons + +| Situation | `skipped` reason string | +|---|---| +| `content-package-maven-plugin` not found in pom | `vault-package-dependencies-no-plugin: content-package-maven-plugin not found in ` | +| Plugin found but no `/` block present | `vault-package-dependencies-no-deps-block: no block under in ` | +| `` block contains no legacy group prefixes | `vault-package-dependencies-no-legacy-groups: no day/cq60 or day/cq560 group prefixes found in ` | + +## Editing strategy + +Surgical XML edit — anchor on ≥3 lines of context before and after the `` block. Use `replace_string_in_file`. Do not re-serialize or reformat any surrounding XML. diff --git a/plugins/aem/cloud-service/skills/migration/SKILL.md b/plugins/aem/cloud-service/skills/migration/SKILL.md index 1d4d8a44..cba6fb7e 100644 --- a/plugins/aem/cloud-service/skills/migration/SKILL.md +++ b/plugins/aem/cloud-service/skills/migration/SKILL.md @@ -22,6 +22,7 @@ This skill drives the **migration workflow**: BPA data, CAM/MCP, **one pattern p | A **BPA CSV** | *"Fix **scheduler** findings using `./path/to/bpa.csv`"* | Fastest path: CSV → cached collection → files | | **CAM + MCP** only | *"Get **scheduler** findings from CAM; I'll pick the project when you list them."* | Agent lists projects → you confirm → MCP fetch ([cam-mcp.md](references/cam-mcp.md)) | | **Just a few files** | *"Migrate **scheduler** in `core/.../MyJob.java`"* | Manual flow: no BPA required | +| **Vault deploy blocker** | *"Fix **vault-package-dependencies** — my package won't install on AEMaaCS."* | Agent scans pom.xml files for `day/cq60/product` Vault deps and removes the `` block | | **OSGi → Cloud Manager** | *"**Scan my config files and create Cloud Manager environment secrets or variables.**"* | Agent **auto-reads** [references/osgi-cfg-json-cloud-manager.md](references/osgi-cfg-json-cloud-manager.md) (full Adobe-aligned rules inlined there); no BPA pattern id | | **HTL lint warnings** | *"Fix **htlLint** issues in `ui.apps`"* | Proactive discovery via `rg` → fix per the HTL lint reference | | **Template modernization** | *"**Migrate my static templates to editable templates and generate Modernize Tools rules.**"* / *"Create editable templates from my static templates."* / *"Generate AEM Modernize Tools structure/component/policy rules."* | Agent **auto-reads** [references/template-modernization/template-modernization-context.md](references/template-modernization/template-modernization-context.md) (shared discovery + structured context), produces a **per-template plan table**, then executes the plan using [editable-template-creation.md](references/template-modernization/editable-template-creation.md) and [aem-modernization.md](references/template-modernization/aem-modernization.md), and validates via [template-modernization-validation.md](references/template-modernization/template-modernization-validation.md). No BPA pattern id. | diff --git a/plugins/aem/cloud-service/test/code-assessment/fixtures/vault-package-dependencies-clean/pom.xml b/plugins/aem/cloud-service/test/code-assessment/fixtures/vault-package-dependencies-clean/pom.xml new file mode 100644 index 00000000..b4a0fadd --- /dev/null +++ b/plugins/aem/cloud-service/test/code-assessment/fixtures/vault-package-dependencies-clean/pom.xml @@ -0,0 +1,23 @@ + + + + 4.0.0 + com.example + example-ui.apps + 1.0.0-SNAPSHOT + content-package + + + + com.day.jcr.vault + content-package-maven-plugin + true + + true + true + adobe/aem6/sample + + + + + diff --git a/plugins/aem/cloud-service/test/code-assessment/fixtures/vault-package-dependencies/pom.xml b/plugins/aem/cloud-service/test/code-assessment/fixtures/vault-package-dependencies/pom.xml new file mode 100644 index 00000000..409e6c2d --- /dev/null +++ b/plugins/aem/cloud-service/test/code-assessment/fixtures/vault-package-dependencies/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + com.example + example-ui.apps + 1.0.0-SNAPSHOT + content-package + + + + com.day.jcr.vault + content-package-maven-plugin + true + + true + true + adobe/aem6/sample + + + day/cq60/product + cq-content + [6.3.0,) + + + day/cq60/product + cq-commerce-content + [1.5.0,) + + + day/cq560/social/commons + cq-social-commons-pkg + [1.7.0,) + + + + + + + diff --git a/plugins/aem/cloud-service/test/code-assessment/run-tests.sh b/plugins/aem/cloud-service/test/code-assessment/run-tests.sh index 77090d68..8e6dc534 100755 --- a/plugins/aem/cloud-service/test/code-assessment/run-tests.sh +++ b/plugins/aem/cloud-service/test/code-assessment/run-tests.sh @@ -252,6 +252,15 @@ assert_absent "no findings when cache is missing" "$OUT" '"pattern":"remove-de rm -f "$RULES_TSV" +echo "[vault-package-dependencies] legacy AEM 6.x Vault install-time deps detected; clean pom not flagged" +OUT="$(run "$FIX/vault-package-dependencies")" +assert_contains "vault-package-dependencies pattern present" "$OUT" '"pattern":"vault-package-dependencies"' +assert_contains "antipattern pom flagged" "$OUT" 'pom.xml' +assert_contains "day/cq60/product group in snippet" "$OUT" 'day/cq60/product' + +OUT="$(run "$FIX/vault-package-dependencies-clean")" +assert_absent "clean vault pom not flagged" "$OUT" 'vault-package-dependencies' + echo "----" echo "PASS=$PASS FAIL=$FAIL" [ "$FAIL" -eq 0 ]