From 67895e5df3988ff7a4e37566b18ac3634f510227 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 12:14:29 -0700 Subject: [PATCH 01/18] fix(ps): add SubscriptionId alias to Verify-Agent.ps1 and Diff-Agent.ps1 Deploy-Agent.ps1 calls both scripts with -SubscriptionId but the param was named -Subscription. This caused Apply-Extras to never run after deploy, so incident platforms, filters, hooks, repos etc. were skipped. --- sreagent-templates/bin/ps/Diff-Agent.ps1 | 2 +- sreagent-templates/bin/ps/Verify-Agent.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sreagent-templates/bin/ps/Diff-Agent.ps1 b/sreagent-templates/bin/ps/Diff-Agent.ps1 index cfba21356..62c8c7b96 100644 --- a/sreagent-templates/bin/ps/Diff-Agent.ps1 +++ b/sreagent-templates/bin/ps/Diff-Agent.ps1 @@ -29,7 +29,7 @@ [CmdletBinding()] param( [Parameter(Mandatory)] - [Alias('s')] + [Alias('s', 'SubscriptionId')] [string]$Subscription, [Parameter(Mandatory)] diff --git a/sreagent-templates/bin/ps/Verify-Agent.ps1 b/sreagent-templates/bin/ps/Verify-Agent.ps1 index 9f1bfd49c..18da04d8b 100644 --- a/sreagent-templates/bin/ps/Verify-Agent.ps1 +++ b/sreagent-templates/bin/ps/Verify-Agent.ps1 @@ -26,7 +26,7 @@ [CmdletBinding()] param( [Parameter(Mandatory)] - [Alias('s')] + [Alias('s', 'SubscriptionId')] [string]$Subscription, [Parameter(Mandatory)] From 37cf8f6d6b538186bfefd1c3c788603019c71d71 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 12:20:08 -0700 Subject: [PATCH 02/18] fix(ps): add SubscriptionId alias to Export-Agent.ps1 and Clone-Agent.ps1 Consistent parameter naming across all PS scripts so callers can use either -Subscription or -SubscriptionId interchangeably. --- sreagent-templates/bin/ps/Clone-Agent.ps1 | 2 ++ sreagent-templates/bin/ps/Export-Agent.ps1 | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sreagent-templates/bin/ps/Clone-Agent.ps1 b/sreagent-templates/bin/ps/Clone-Agent.ps1 index 9c0362229..7dc9dcae3 100644 --- a/sreagent-templates/bin/ps/Clone-Agent.ps1 +++ b/sreagent-templates/bin/ps/Clone-Agent.ps1 @@ -54,11 +54,13 @@ param( [string]$Source, [string]$FromAgent, [string]$FromResourceGroup, + [Alias('FromSubscriptionId')] [string]$FromSubscription, [Parameter(Mandatory)][string]$AgentName, [Parameter(Mandatory)][string]$ResourceGroup, [string]$Location, [string]$TargetResourceGroups, + [Alias('SubscriptionId')] [string]$Subscription, [switch]$ValidateOnly, [switch]$SkipExtras, diff --git a/sreagent-templates/bin/ps/Export-Agent.ps1 b/sreagent-templates/bin/ps/Export-Agent.ps1 index e13636a63..c8cbaad0e 100644 --- a/sreagent-templates/bin/ps/Export-Agent.ps1 +++ b/sreagent-templates/bin/ps/Export-Agent.ps1 @@ -61,7 +61,7 @@ [CmdletBinding()] param( [Parameter(Mandatory)] - [Alias('s')] + [Alias('s', 'SubscriptionId')] [string]$Subscription, [Parameter(Mandatory)] From 25081259a07a7113e5271a9dcca81267b5e2c4c8 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 12:25:05 -0700 Subject: [PATCH 03/18] =?UTF-8?q?fix:=20PS=207.3+=20az/curl=20string=20arr?= =?UTF-8?q?ay=20splitting=20=E2=86=92=20jq=20parse=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Invoke-Jq: use begin/process/end to accumulate pipeline input before piping to jq, so multi-element arrays from native commands are joined correctly. Verify-Agent, Diff-Agent, Export-Agent, Apply-Extras: wrap az rest / curl invocations in (-join "`n") to coalesce string[] into single JSON strings before piping to jq or ConvertFrom-Json. --- sreagent-templates/bicep/Apply-Extras.ps1 | 2 +- sreagent-templates/bin/ps/Diff-Agent.ps1 | 4 ++-- sreagent-templates/bin/ps/Export-Agent.ps1 | 8 ++++---- sreagent-templates/bin/ps/Invoke-Jq.ps1 | 13 +++++++++++-- sreagent-templates/bin/ps/Verify-Agent.ps1 | 6 +++--- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/sreagent-templates/bicep/Apply-Extras.ps1 b/sreagent-templates/bicep/Apply-Extras.ps1 index 45304e20e..c96762322 100644 --- a/sreagent-templates/bicep/Apply-Extras.ps1 +++ b/sreagent-templates/bicep/Apply-Extras.ps1 @@ -87,7 +87,7 @@ $ArmBase = "https://management.azure.com/subscriptions/$Subscription/resourceGro # ── Resolve agent endpoint and UAMI ──────────────────────────────────────── try { - $agentRaw = az rest -m GET --url "$ArmBase`?api-version=$ApiVersion" -o json 2>$null + $agentRaw = (az rest -m GET --url "$ArmBase`?api-version=$ApiVersion" -o json 2>$null) -join "`n" $agentObj = $agentRaw | ConvertFrom-Json } catch { $agentObj = $null diff --git a/sreagent-templates/bin/ps/Diff-Agent.ps1 b/sreagent-templates/bin/ps/Diff-Agent.ps1 index 62c8c7b96..f330bbfe8 100644 --- a/sreagent-templates/bin/ps/Diff-Agent.ps1 +++ b/sreagent-templates/bin/ps/Diff-Agent.ps1 @@ -77,7 +77,7 @@ $ARM_BASE = "https://management.azure.com/subscriptions/${Subscription}/resou # ─────────────────────────── Check if agent exists ─────────────────────────── -$AgentJson = az rest -m GET --url "${ARM_BASE}?api-version=${API_VERSION}" -o json 2>$null +$AgentJson = (az rest -m GET --url "${ARM_BASE}?api-version=${API_VERSION}" -o json 2>$null) -join "`n" if (-not $AgentJson) { $AgentJson = '{}' } $Endpoint = $AgentJson | Invoke-Jq -Raw -Filter '.properties.agentEndpoint // empty' @@ -154,7 +154,7 @@ if (-not $Token) { function Invoke-Dp { param([string]$Path) - curl -sS "${Endpoint}${Path}" -H "Authorization: Bearer $Token" 2>$null + (curl -sS "${Endpoint}${Path}" -H "Authorization: Bearer $Token" 2>$null) -join "`n" } # ─────────────────────────── Results tracking ─────────────────────────── diff --git a/sreagent-templates/bin/ps/Export-Agent.ps1 b/sreagent-templates/bin/ps/Export-Agent.ps1 index c8cbaad0e..bb53faf25 100644 --- a/sreagent-templates/bin/ps/Export-Agent.ps1 +++ b/sreagent-templates/bin/ps/Export-Agent.ps1 @@ -188,7 +188,7 @@ function Write-Yaml { function Invoke-ArmGet { param([string]$Url) try { - $result = az rest -m GET --url "${Url}?api-version=${API_VERSION}" -o json 2>$null + $result = (az rest -m GET --url "${Url}?api-version=${API_VERSION}" -o json 2>$null) -join "`n" if ($LASTEXITCODE -ne 0 -or -not $result) { return 'null' } return $result } catch { @@ -201,7 +201,7 @@ function Invoke-ArmList { param([string]$ChildType) $url = "${ARM_BASE}/${ChildType}?api-version=${API_VERSION}" try { - $result = az rest -m GET --url $url -o json 2>$null + $result = (az rest -m GET --url $url -o json 2>$null) -join "`n" if ($LASTEXITCODE -ne 0 -or -not $result) { return '[]' } return ($result | Invoke-Jq -Compact -Filter '.value // []') } catch { @@ -230,7 +230,7 @@ function Invoke-DpGet { param([string]$Path) $token = Get-DpToken try { - $result = curl -sS -f -H "Authorization: Bearer $token" "${AGENT_ENDPOINT}${Path}" 2>$null + $result = (curl -sS -f -H "Authorization: Bearer $token" "${AGENT_ENDPOINT}${Path}" 2>$null) -join "`n" if ($LASTEXITCODE -ne 0 -or -not $result) { return 'null' } return $result } catch { @@ -720,7 +720,7 @@ _log 'Checking for webhook bridge (Logic App)...' $BRIDGE_EXISTS = $false $bridgeId = "/subscriptions/${Subscription}/resourceGroups/${ResourceGroup}/providers/Microsoft.Logic/workflows/${AgentName}-webhook-bridge" try { - $BRIDGE_JSON = az resource show --ids $bridgeId -o json 2>$null + $BRIDGE_JSON = (az resource show --ids $bridgeId -o json 2>$null) -join "`n" if ($LASTEXITCODE -eq 0 -and $BRIDGE_JSON -and $BRIDGE_JSON -ne 'null') { $BRIDGE_EXISTS = $true _log " Found webhook bridge: ${AgentName}-webhook-bridge" diff --git a/sreagent-templates/bin/ps/Invoke-Jq.ps1 b/sreagent-templates/bin/ps/Invoke-Jq.ps1 index f02d855e8..987fa0143 100644 --- a/sreagent-templates/bin/ps/Invoke-Jq.ps1 +++ b/sreagent-templates/bin/ps/Invoke-Jq.ps1 @@ -32,7 +32,15 @@ function Invoke-Jq { [switch]$Slurp, [switch]$ExitTest # like jq -e ) + begin { + # Accumulate all pipeline input so multi-line JSON (e.g. from az rest) + # and ($a, $b) | Invoke-Jq both work correctly. + $inputLines = [System.Collections.Generic.List[string]]::new() + } process { + if ($InputJson) { $inputLines.Add($InputJson) } + } + end { $tmpFilter = [System.IO.Path]::GetTempFileName() try { Set-Content -Path $tmpFilter -Value $Filter -NoNewline -Encoding UTF8 @@ -46,8 +54,9 @@ function Invoke-Jq { if ($InputFile) { return (jq @flags $InputFile) } - elseif ($InputJson) { - return ($InputJson | jq @flags) + elseif ($inputLines.Count -gt 0) { + $joined = $inputLines -join "`n" + return ($joined | jq @flags) } else { return (jq @flags) diff --git a/sreagent-templates/bin/ps/Verify-Agent.ps1 b/sreagent-templates/bin/ps/Verify-Agent.ps1 index 18da04d8b..a06d7ca9b 100644 --- a/sreagent-templates/bin/ps/Verify-Agent.ps1 +++ b/sreagent-templates/bin/ps/Verify-Agent.ps1 @@ -97,7 +97,7 @@ function Get-ExpList { $API_VERSION = '2025-05-01-preview' $ARM_BASE = "https://management.azure.com/subscriptions/${Subscription}/resourceGroups/${ResourceGroup}/providers/Microsoft.App/agents/${AgentName}" -$AgentJson = az rest -m GET --url "${ARM_BASE}?api-version=${API_VERSION}" -o json 2>$null +$AgentJson = (az rest -m GET --url "${ARM_BASE}?api-version=${API_VERSION}" -o json 2>$null) -join "`n" if (-not $AgentJson) { $AgentJson = '{}' } $Endpoint = $AgentJson | Invoke-Jq -Raw -Filter '.properties.agentEndpoint // empty' @@ -114,12 +114,12 @@ if (-not $Token) { function Invoke-Dp { param([string]$Path) - curl -sS "${Endpoint}${Path}" -H "Authorization: Bearer $Token" 2>$null + (curl -sS "${Endpoint}${Path}" -H "Authorization: Bearer $Token" 2>$null) -join "`n" } function Invoke-Arm { param([string]$Path) - $result = az rest -m GET --url "${ARM_BASE}${Path}?api-version=${API_VERSION}" -o json 2>$null + $result = (az rest -m GET --url "${ARM_BASE}${Path}?api-version=${API_VERSION}" -o json 2>$null) -join "`n" if (-not $result) { return '{}' } return $result } From 2e1c85ce7f38430d24a9433493e467e4bcda6dce Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 11:17:24 -0700 Subject: [PATCH 04/18] feat: add color output to verify-agent.sh Green checkmarks for passing checks, red for failures. Bold header/summary, cyan for links/agent name. Colors auto-disabled when output is piped (non-TTY). --- sreagent-templates/bin/verify-agent.sh | 39 +++++++++++++++++--------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/sreagent-templates/bin/verify-agent.sh b/sreagent-templates/bin/verify-agent.sh index 6186dc6f2..40fb653aa 100755 --- a/sreagent-templates/bin/verify-agent.sh +++ b/sreagent-templates/bin/verify-agent.sh @@ -9,6 +9,13 @@ set -uo pipefail +# ── Colors ── +if [[ -t 1 ]]; then + GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[0;33m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m' +else + GREEN='' RED='' YELLOW='' CYAN='' BOLD='' NC='' +fi + SUB="${1:?subscription-id required}" RG="${2:?resource-group required}" AGENT="${3:?agent-name required}" @@ -71,22 +78,22 @@ RESULTS="" check() { local name="$1" actual="$2" expected="$3" if [[ "$expected" == "-" ]]; then - RESULTS="${RESULTS}\n ${name}|${actual}|—|✅" + RESULTS="${RESULTS}\n ${name}|${actual}|—|${GREEN}✅${NC}" PASS=$((PASS + 1)) elif [[ "$actual" == "$expected" ]]; then - RESULTS="${RESULTS}\n ${name}|${actual}|${expected}|✅ PASS" + RESULTS="${RESULTS}\n ${name}|${actual}|${expected}|${GREEN}✅ PASS${NC}" PASS=$((PASS + 1)) else - RESULTS="${RESULTS}\n ${name}|${actual}|${expected}|❌ FAIL" + RESULTS="${RESULTS}\n ${name}|${actual}|${expected}|${RED}❌ FAIL${NC}" FAIL=$((FAIL + 1)) fi } echo "" -echo "═══════════════════════════════════════════════════" -echo " SRE Agent Verification: ${AGENT}" -echo " Endpoint: ${ENDPOINT}" -echo "═══════════════════════════════════════════════════" +echo -e "${BOLD}═══════════════════════════════════════════════════${NC}" +echo -e " ${BOLD}SRE Agent Verification:${NC} ${CYAN}${AGENT}${NC}" +echo -e " ${BOLD}Endpoint:${NC} ${CYAN}${ENDPOINT}${NC}" +echo -e "${BOLD}═══════════════════════════════════════════════════${NC}" echo "" # ── Agent properties ── @@ -116,7 +123,7 @@ check "Connectors (healthy)" "$CONN_HEALTHY" "$CONN_CT" # Show errored connectors explicitly if [[ "$CONN_ERRORED" -gt 0 ]]; then ERRORED_LIST=$(echo "$CONNECTORS" | jq -r '.value[] | select(.properties.provisioningState != "Succeeded" and .properties.provisioningState != "Running") | "\(.name) (\(.properties.dataConnectorType)): \(.properties.provisioningState)"') - RESULTS="${RESULTS}\n ⚠ Errored connectors|${ERRORED_LIST}||❌ FAIL" + RESULTS="${RESULTS}\n ⚠ Errored connectors|${ERRORED_LIST}||${RED}❌ FAIL${NC}" FAIL=$((FAIL + 1)) fi CONN_NAMES=$(echo "$CONNECTORS" | jq -r '.value[].name' 2>/dev/null | sort | tr '\n' ', ' | sed 's/,$//') @@ -197,18 +204,22 @@ check "Repos" "$REPO_CT" "$EXP_REPO_CT" # ── Print results ── echo "" -printf " %-25s %-10s %-10s %s\n" "Check" "Actual" "Expected" "Result" +printf " ${BOLD}%-25s %-10s %-10s %s${NC}\n" "Check" "Actual" "Expected" "Result" printf " %-25s %-10s %-10s %s\n" "─────────────────────────" "──────────" "──────────" "──────" echo -e "$RESULTS" | while IFS='|' read -r name actual expected result; do [[ -z "$name" ]] && continue - printf " %-25s %-10s %-10s %s\n" "$name" "$actual" "$expected" "$result" + printf " %-25s %-10s %-10s %b\n" "$name" "$actual" "$expected" "$result" done echo "" -echo "═══════════════════════════════════════════════════" -echo " Results: ${PASS} passed, ${FAIL} failed" -echo " Portal: https://sre.azure.com/#/agent/${SUB}/${RG}/${AGENT}" -echo "═══════════════════════════════════════════════════" +echo -e "${BOLD}═══════════════════════════════════════════════════${NC}" +if [[ "$FAIL" -gt 0 ]]; then + echo -e " Results: ${GREEN}${PASS} passed${NC}, ${RED}${FAIL} failed${NC}" +else + echo -e " Results: ${GREEN}${PASS} passed${NC}, ${FAIL} failed" +fi +echo -e " Portal: ${CYAN}https://sre.azure.com/#/agent/${SUB}/${RG}/${AGENT}${NC}" +echo -e "${BOLD}═══════════════════════════════════════════════════${NC}" echo "" [[ "$FAIL" -gt 0 ]] && exit 1 From 89d831d2cc4d962346a5787e91a8779305105016 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 12:37:14 -0700 Subject: [PATCH 05/18] =?UTF-8?q?fix(ps):=20fix=20jq=20join=20filter=20quo?= =?UTF-8?q?ting=20in=20Get-ExpList=20(join(`,`)=20=E2=86=92=20join(`",`"))?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sreagent-templates/bin/ps/Verify-Agent.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sreagent-templates/bin/ps/Verify-Agent.ps1 b/sreagent-templates/bin/ps/Verify-Agent.ps1 index a06d7ca9b..6d6d994aa 100644 --- a/sreagent-templates/bin/ps/Verify-Agent.ps1 +++ b/sreagent-templates/bin/ps/Verify-Agent.ps1 @@ -87,7 +87,7 @@ function Get-Exp { function Get-ExpList { param([string]$JqPath) if ($ExpectedConfig) { - return ($ExpectedConfig | Invoke-Jq -Raw -Filter "$JqPath // [] | sort | join(`,`)") + return ($ExpectedConfig | Invoke-Jq -Raw -Filter "$JqPath // [] | sort | join(`",`")") } return '' } From 042ea5d8bc250e4f1636812c0a8be8ab5a99d5cd Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 12:45:46 -0700 Subject: [PATCH 06/18] fix(ps): wrap iterator jq paths in [] to prevent sort-on-string error --- sreagent-templates/bin/ps/Verify-Agent.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sreagent-templates/bin/ps/Verify-Agent.ps1 b/sreagent-templates/bin/ps/Verify-Agent.ps1 index 6d6d994aa..1caef4f0e 100644 --- a/sreagent-templates/bin/ps/Verify-Agent.ps1 +++ b/sreagent-templates/bin/ps/Verify-Agent.ps1 @@ -197,7 +197,7 @@ $ConnCt = $Connectors | jq '.value | length' $ConnHealthy = $Connectors | Invoke-Jq -Filter '[.value[] | select(.properties.provisioningState == "Succeeded")] | length' $ConnNames = ($Connectors | jq -r '.value[].name' 2>$null | Sort-Object) -join ',' $ExpConnCt = Get-Exp '.connectors | length' -$ExpConnNames = Get-ExpList '.connectors[].name' +$ExpConnNames = Get-ExpList '[.connectors[].name]' Add-Check 'Connectors (total)' $ConnCt $ExpConnCt Add-Check 'Connectors (healthy)' $ConnHealthy $ConnCt @@ -297,7 +297,7 @@ $FilterCt = $Filters | Invoke-Jq -Filter 'if type == "array" then length else 0 if (-not $FilterCt) { $FilterCt = '0' } $FilterNames = ($Filters | jq -r '.[].id' 2>$null | Sort-Object) -join ',' $ExpFilterCt = Get-Exp '.responsePlans | length' -$ExpFilterNames = Get-ExpList '.responsePlans[].name' +$ExpFilterNames = Get-ExpList '[.responsePlans[].name]' Add-Check 'Response Plans' $FilterCt $ExpFilterCt if ($ExpFilterNames) { From e12c012c766fe21e57bb2514b55ff93f70b24162 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 13:34:27 -0700 Subject: [PATCH 07/18] fix(ps): fix Invoke-Jq no-input hang, curl max-time, raw jq in Verify-Agent - Invoke-Jq: use jq -n when called with no pipeline input (prevents blocking on stdin) - Export-Agent.ps1 + export-agent.sh: add --max-time 10 to curl in dp_get/Invoke-DpGet - Verify-Agent.ps1: replace 2 raw jq calls with Invoke-Jq wrapper (fixes parse error after verify) --- sreagent-templates/bin/export-agent.sh | 2 +- sreagent-templates/bin/ps/Export-Agent.ps1 | 2 +- sreagent-templates/bin/ps/Invoke-Jq.ps1 | 4 +++- sreagent-templates/bin/ps/Verify-Agent.ps1 | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/sreagent-templates/bin/export-agent.sh b/sreagent-templates/bin/export-agent.sh index b4fe0b168..346fc0b50 100755 --- a/sreagent-templates/bin/export-agent.sh +++ b/sreagent-templates/bin/export-agent.sh @@ -150,7 +150,7 @@ dp_get() { local path="$1" local token token=$(_dp_token) - curl -sS -f -H "Authorization: Bearer ${token}" "${AGENT_ENDPOINT}${path}" 2>/dev/null || echo "null" + curl -sS -f --max-time 10 -H "Authorization: Bearer ${token}" "${AGENT_ENDPOINT}${path}" 2>/dev/null || echo "null" } # Download a file from data-plane to local path diff --git a/sreagent-templates/bin/ps/Export-Agent.ps1 b/sreagent-templates/bin/ps/Export-Agent.ps1 index bb53faf25..03061a5c8 100644 --- a/sreagent-templates/bin/ps/Export-Agent.ps1 +++ b/sreagent-templates/bin/ps/Export-Agent.ps1 @@ -230,7 +230,7 @@ function Invoke-DpGet { param([string]$Path) $token = Get-DpToken try { - $result = (curl -sS -f -H "Authorization: Bearer $token" "${AGENT_ENDPOINT}${Path}" 2>$null) -join "`n" + $result = (curl -sS -f --max-time 10 -H "Authorization: Bearer $token" "${AGENT_ENDPOINT}${Path}" 2>$null) -join "`n" if ($LASTEXITCODE -ne 0 -or -not $result) { return 'null' } return $result } catch { diff --git a/sreagent-templates/bin/ps/Invoke-Jq.ps1 b/sreagent-templates/bin/ps/Invoke-Jq.ps1 index 987fa0143..b78b9d97b 100644 --- a/sreagent-templates/bin/ps/Invoke-Jq.ps1 +++ b/sreagent-templates/bin/ps/Invoke-Jq.ps1 @@ -59,7 +59,9 @@ function Invoke-Jq { return ($joined | jq @flags) } else { - return (jq @flags) + # No pipeline input and no InputFile — use jq -n (null-input mode) + # so jq doesn't block waiting on stdin. + return (jq '-n' @flags) } } finally { diff --git a/sreagent-templates/bin/ps/Verify-Agent.ps1 b/sreagent-templates/bin/ps/Verify-Agent.ps1 index 1caef4f0e..1f28df28d 100644 --- a/sreagent-templates/bin/ps/Verify-Agent.ps1 +++ b/sreagent-templates/bin/ps/Verify-Agent.ps1 @@ -276,7 +276,7 @@ if ($ExpPromptNames) { $Tasks = Invoke-Dp '/api/v1/scheduledtasks' $TaskCt = $Tasks | Invoke-Jq -Filter 'if type == "array" then length else 0 end' if (-not $TaskCt) { $TaskCt = '0' } -$TaskUnique = $Tasks | jq '[.[].name] | unique | length' 2>$null +$TaskUnique = $Tasks | Invoke-Jq -Filter '[.[].name] | unique | length' if (-not $TaskUnique) { $TaskUnique = '0' } $TaskNames = $Tasks | Invoke-Jq -Raw -Filter '[.[].name] | unique | sort | join(",")' $ExpTaskCt = Get-Exp '.scheduledTasks | length' @@ -295,7 +295,7 @@ if ($TaskCt -ne $TaskUnique) { $Filters = Invoke-Dp '/api/v1/incidentPlayground/filters' $FilterCt = $Filters | Invoke-Jq -Filter 'if type == "array" then length else 0 end' if (-not $FilterCt) { $FilterCt = '0' } -$FilterNames = ($Filters | jq -r '.[].id' 2>$null | Sort-Object) -join ',' +$FilterNames = ($Filters | Invoke-Jq -Raw -Filter '[.[].id] | sort | join(",")' ) $ExpFilterCt = Get-Exp '.responsePlans | length' $ExpFilterNames = Get-ExpList '[.responsePlans[].name]' From 76b17004394d58da81101a6d5ed5c800b83aff9b Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 13:36:47 -0700 Subject: [PATCH 08/18] fix(ps): fix ConvertTo-Yaml pipeline accumulation (begin/process/end) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same root cause as Invoke-Jq: Invoke-Jq returns string[] (one line per jq output line). Piping that to ConvertTo-Yaml called process{} once per line — each line is not valid JSON, causing json.load() to fail. Fix: accumulate all pipeline input in begin/process/end before passing to python3. --- sreagent-templates/bin/ps/Export-Agent.ps1 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sreagent-templates/bin/ps/Export-Agent.ps1 b/sreagent-templates/bin/ps/Export-Agent.ps1 index 03061a5c8..646d6ba4a 100644 --- a/sreagent-templates/bin/ps/Export-Agent.ps1 +++ b/sreagent-templates/bin/ps/Export-Agent.ps1 @@ -159,7 +159,11 @@ function _fail { param([string]$Msg) Write-Host " ERROR: $Msg" -ForegroundColor # ── JSON → YAML via python3 ── function ConvertTo-Yaml { param([Parameter(ValueFromPipeline)][string]$Json) - $result = $Json | python3 -c @" + begin { $inputLines = [System.Collections.Generic.List[string]]::new() } + process { if ($Json) { $inputLines.Add($Json) } } + end { + $fullJson = $inputLines -join "`n" + $result = $fullJson | python3 -c @" import sys, json, yaml def strip_nulls(obj): @@ -173,10 +177,11 @@ data = json.load(sys.stdin) data = strip_nulls(data) yaml.dump(data, sys.stdout, default_flow_style=False, sort_keys=False, allow_unicode=True) "@ - if ($LASTEXITCODE -ne 0 -or -not $result) { - throw "python3 YAML conversion failed (exit code: $LASTEXITCODE)" + if ($LASTEXITCODE -ne 0 -or -not $result) { + throw "python3 YAML conversion failed (exit code: $LASTEXITCODE)" + } + return $result } - return $result } function Write-Yaml { From f4a24fa0b7727166dd7bd64ea960f130f2d7babf Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 13:44:37 -0700 Subject: [PATCH 09/18] fix(ps): fix agent.json/expected-config.json not written (remove -InputFile '/dev/null') jq reads /dev/null as empty input (0 JSON values) so the filter ran 0 times and produced no output. Fix: remove -InputFile '/dev/null' so Invoke-Jq falls through to the jq -n path (null input, runs once). --- sreagent-templates/bin/ps/Export-Agent.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sreagent-templates/bin/ps/Export-Agent.ps1 b/sreagent-templates/bin/ps/Export-Agent.ps1 index 646d6ba4a..4b74aed73 100644 --- a/sreagent-templates/bin/ps/Export-Agent.ps1 +++ b/sreagent-templates/bin/ps/Export-Agent.ps1 @@ -1054,7 +1054,7 @@ Invoke-Jq -Filter '{ '--arg', 'action', $ACTION_MODE, '--slurpfile', 'targetRgs', $trgTmpFile, '--arg', 'enableBridge', $bridgeBool - ) -InputFile '/dev/null' | Set-Content -Path (Join-Path $EXPORT_DIR 'agent.json') -Encoding utf8 + ) | Set-Content -Path (Join-Path $EXPORT_DIR 'agent.json') -Encoding utf8 Remove-Item $trgTmpFile -Force -ErrorAction SilentlyContinue # Apply --set overrides @@ -1288,7 +1288,7 @@ Invoke-Jq -Filter '{ '--slurpfile', 'tasks', (Join-Path $ecTmpDir 'tasks.json'), '--slurpfile', 'plans', (Join-Path $ecTmpDir 'plans.json'), '--slurpfile', 'repos', (Join-Path $ecTmpDir 'repos.json') - ) -InputFile '/dev/null' | Set-Content -Path (Join-Path $EXPORT_DIR 'expected-config.json') -Encoding utf8 + ) | Set-Content -Path (Join-Path $EXPORT_DIR 'expected-config.json') -Encoding utf8 Remove-Item $ecTmpDir -Recurse -Force -ErrorAction SilentlyContinue _log 'Wrote expected-config.json' From 7c6820720a5cd7b2b49988be20a3bb551f5e8bac Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 13:55:59 -0700 Subject: [PATCH 10/18] fix(ps): replace Python -c multiline with temp file in Assemble-Agent.ps1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PS 7.3+ Standard argument passing mangles multiline strings passed to native commands via -c. Write each Python script to a temp .py file and execute the file directly — no PS arg mangling possible. Affects: Resolve-FileRefs, Collect-Config (YAML), Resolve-EnvVars, knowledge item builder. --- sreagent-templates/bicep/Assemble-Agent.ps1 | 23 ++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/sreagent-templates/bicep/Assemble-Agent.ps1 b/sreagent-templates/bicep/Assemble-Agent.ps1 index 9edf3c1b9..71035511a 100644 --- a/sreagent-templates/bicep/Assemble-Agent.ps1 +++ b/sreagent-templates/bicep/Assemble-Agent.ps1 @@ -135,7 +135,10 @@ print(json.dumps(resolve(data))) '@ try { - $result = $Json | & $Python -c $pyScript $BaseDir 2>$null + $pyTmp = [System.IO.Path]::GetTempFileName() + '.py' + Set-Content -Path $pyTmp -Value $pyScript -Encoding UTF8 + $result = $Json | & $Python $pyTmp $BaseDir 2>$null + Remove-Item $pyTmp -Force -ErrorAction SilentlyContinue if ($LASTEXITCODE -eq 0 -and $result) { return $result } } catch {} return $Json @@ -168,7 +171,10 @@ with open(sys.argv[1]) as fh: print(json.dumps(data)) '@ try { - $item = & $Python -c $pyYaml $f.FullName 2>$null + $pyTmp = [System.IO.Path]::GetTempFileName() + '.py' + Set-Content -Path $pyTmp -Value $pyYaml -Encoding UTF8 + $item = & $Python $pyTmp $f.FullName 2>$null + Remove-Item $pyTmp -Force -ErrorAction SilentlyContinue if ($LASTEXITCODE -ne 0 -or -not $item) { continue } # Use --slurpfile to safely pass JSON without --argjson quoting issues $tmpItem = [System.IO.Path]::GetTempFileName() @@ -215,7 +221,10 @@ print(json.dumps(sub(data))) '@ try { - $result = $Json | & $Python -c $pyScript 2>$null + $pyTmp = [System.IO.Path]::GetTempFileName() + '.py' + Set-Content -Path $pyTmp -Value $pyScript -Encoding UTF8 + $result = $Json | & $Python $pyTmp 2>$null + Remove-Item $pyTmp -Force -ErrorAction SilentlyContinue if ($LASTEXITCODE -eq 0 -and $result) { return $result } } catch {} return $Json @@ -413,12 +422,16 @@ if ($mdFiles.Count -gt 0) { # Build JSON item via Python to avoid jq --arg quoting issues with large content $tmpContent = [System.IO.Path]::GetTempFileName() Set-Content -Path $tmpContent -Value $content -NoNewline -Encoding UTF8 - $item = & $Python -c @" + $pyKnowledge = @' import json, sys with open(sys.argv[1]) as f: content = f.read() print(json.dumps({"name": sys.argv[2], "type": "KnowledgeText", "content": content})) -"@ $tmpContent $fname 2>$null +'@ + $pyTmp = [System.IO.Path]::GetTempFileName() + '.py' + Set-Content -Path $pyTmp -Value $pyKnowledge -Encoding UTF8 + $item = & $Python $pyTmp $tmpContent $fname 2>$null + Remove-Item $pyTmp -Force -ErrorAction SilentlyContinue Remove-Item $tmpContent -ErrorAction SilentlyContinue if ($LASTEXITCODE -eq 0 -and $item) { $tmpItem = [System.IO.Path]::GetTempFileName() From 60f34dfbbc88c26e00e770b40088ebd3e307d5f4 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 14:13:31 -0700 Subject: [PATCH 11/18] fix: ConvertTo-Yaml return string[] joined with newlines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PS captures native-command stdout as string[] (one item per line). ConvertTo-Yaml was returning the raw string[] from python3 -c. Set-Content -NoNewline on a string[] concatenates without any separator, producing flat YAML with no newlines. Fix: join with `n before returning so callers receive a single properly-formatted YAML string. This caused all skills/subagents/hooks/prompts/repos/tasks/filters to be 0 after cloning — the exported YAML files were unparseable by python yaml.safe_load during re-assembly. --- sreagent-templates/bin/ps/Export-Agent.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sreagent-templates/bin/ps/Export-Agent.ps1 b/sreagent-templates/bin/ps/Export-Agent.ps1 index 4b74aed73..b61276be9 100644 --- a/sreagent-templates/bin/ps/Export-Agent.ps1 +++ b/sreagent-templates/bin/ps/Export-Agent.ps1 @@ -180,7 +180,9 @@ yaml.dump(data, sys.stdout, default_flow_style=False, sort_keys=False, allow_uni if ($LASTEXITCODE -ne 0 -or -not $result) { throw "python3 YAML conversion failed (exit code: $LASTEXITCODE)" } - return $result + # PS captures native-command stdout as string[] (one per line). + # Join with newlines so Set-Content -NoNewline writes proper YAML. + return ($result -join "`n") } } From 861a9d2cdaee74bf118799f6c0fa1758e2d196cf Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 14:21:47 -0700 Subject: [PATCH 12/18] fix: add -TimeoutSec 30 to all Invoke-RestMethod/WebRequest calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply-Extras.ps1 had no timeout on any Invoke-RestMethod or Invoke-WebRequest call. Endpoints that accept TCP but never respond (unconfigured GitHub OAuth, ADO, incident-platform status polling) caused indefinite hangs — same root cause as the curl --max-time 10 fix in Export-Agent.ps1 / export-agent.sh. Adds -TimeoutSec 30 uniformly to all 20 calls. --- sreagent-templates/bicep/Apply-Extras.ps1 | 40 +++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/sreagent-templates/bicep/Apply-Extras.ps1 b/sreagent-templates/bicep/Apply-Extras.ps1 index c96762322..e7892321a 100644 --- a/sreagent-templates/bicep/Apply-Extras.ps1 +++ b/sreagent-templates/bicep/Apply-Extras.ps1 @@ -210,7 +210,7 @@ function DataPlane-UploadTarball { "Content-Type" = "application/gzip" } $bytes = [System.IO.File]::ReadAllBytes($tarball) - $null = Invoke-RestMethod -Uri $Url -Method Post -Headers $headers -Body $bytes + $null = Invoke-RestMethod -TimeoutSec 30 -Uri $Url -Method Post -Headers $headers -Body $bytes Write-Host " ok" } catch { Write-Host " FAILED - POST $Url" @@ -254,7 +254,7 @@ function DataPlane-UploadMultipart { $fullUrl = "${Url}?triggerIndexing=$Trigger" $headers = @{ Authorization = "Bearer $token" } - $null = Invoke-WebRequest -Uri $fullUrl -Method Post ` + $null = Invoke-WebRequest -TimeoutSec 30 -Uri $fullUrl -Method Post ` -Headers $headers ` -ContentType "multipart/form-data; boundary=$boundary" ` -Body $bodyArray @@ -280,7 +280,7 @@ function DataPlane-PostJson { "Content-Type" = "application/json" } $bodyJson = $BodyObj | ConvertTo-Json -Compress -Depth 20 - $null = Invoke-RestMethod -Uri $Url -Method Post -Headers $headers -Body $bodyJson -ContentType "application/json" + $null = Invoke-RestMethod -TimeoutSec 30 -Uri $Url -Method Post -Headers $headers -Body $bodyJson -ContentType "application/json" Write-Host " ok" } catch { Write-Host " FAILED - POST $Url" @@ -304,7 +304,7 @@ function DataPlane-PutExtended { Authorization = "Bearer $token" "Content-Type" = "application/json" } - $null = Invoke-RestMethod -Uri $url -Method Put -Headers $headers -Body $body -ContentType "application/json" + $null = Invoke-RestMethod -TimeoutSec 30 -Uri $url -Method Put -Headers $headers -Body $body -ContentType "application/json" Write-Host " ok $Kind/$Name" } catch { Write-Host " FAILED - PUT $Kind/$Name" @@ -408,7 +408,7 @@ if ($ifCount -gt 0) { Authorization = "Bearer $token" "Content-Type" = "application/json" } - $null = Invoke-RestMethod -Uri "$AgentEndpoint/api/v2/extendedAgent/incidentFilters/$encodedName" ` + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/extendedAgent/incidentFilters/$encodedName" ` -Method Put -Headers $headers -Body $body -ContentType "application/json" Write-Host " data-plane PUT incidentFilters/$name" Write-Host " ok" @@ -446,7 +446,7 @@ if ($ifCount -gt 0) { Authorization = "Bearer $token" "Content-Type" = "application/json" } - $resp = Invoke-WebRequest -Uri "$AgentEndpoint/api/v1/incidentPlayground/handlers/$name" ` + $resp = Invoke-WebRequest -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/incidentPlayground/handlers/$name" ` -Method Put -Headers $headers -Body $handlerBody -ContentType "application/json" ` -UseBasicParsing $httpCode = $resp.StatusCode @@ -649,7 +649,7 @@ if ($synthDir -and (Test-Path $synthDir -PathType Container)) { "Content-Type" = "application/gzip" } $bytes = [System.IO.File]::ReadAllBytes($tarball) - $null = Invoke-RestMethod -Uri "$AgentEndpoint/api/v1/WorkspaceMemory/synthesized-knowledge" ` + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/WorkspaceMemory/synthesized-knowledge" ` -Method Post -Headers $headers -Body $bytes Write-Host " ok" } catch { @@ -837,7 +837,7 @@ if ($htCount -gt 0) { $token = Get-DpToken $headers = @{ Authorization = "Bearer $token" } try { - $existingTriggers = Invoke-RestMethod -Uri "$AgentEndpoint/api/v1/httpTriggers" -Headers $headers + $existingTriggers = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/httpTriggers" -Headers $headers } catch { $existingTriggers = @() } @@ -861,7 +861,7 @@ if ($htCount -gt 0) { if (-not $HttpTriggerUrl) { $HttpTriggerUrl = $existingUrl } } else { try { - $resp = Invoke-RestMethod -Uri "$AgentEndpoint/api/v1/httptriggers/create" ` + $resp = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/httptriggers/create" ` -Method Post -Headers $headers -Body $bodyJson -ContentType "application/json" $triggerUrl = if ($resp.triggerUrl) { $resp.triggerUrl } else { "created" } Write-Host " httpTrigger/${name}: $triggerUrl" @@ -975,7 +975,7 @@ if ($DpTokenAvailable) { "Content-Type" = "application/json" } $body = @{ accessToken = $env:GITHUB_PAT } | ConvertTo-Json -Compress - $null = Invoke-RestMethod -Uri "$AgentEndpoint/api/v1/Github/auth/pat" ` + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/Github/auth/pat" ` -Method Post -Headers $headers -Body $body -ContentType "application/json" Write-Host " ok" } catch { @@ -995,7 +995,7 @@ if ($DpTokenAvailable) { "Content-Type" = "application/json" } $body = @{ accessToken = $env:ADO_PAT } | ConvertTo-Json -Compress - $null = Invoke-RestMethod -Uri "$AgentEndpoint/api/v1/AzureDevOps/auth/pat?organization=$($env:ADO_ORG)" ` + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/AzureDevOps/auth/pat?organization=$($env:ADO_ORG)" ` -Method Post -Headers $headers -Body $body -ContentType "application/json" Write-Host " ok" } catch { @@ -1014,7 +1014,7 @@ if ($DpTokenAvailable) { "Content-Type" = "application/json" } $body = @{ aadAccessToken = $aadToken } | ConvertTo-Json -Compress - $null = Invoke-RestMethod -Uri "$AgentEndpoint/api/v1/AzureDevOps/aadauth/complete?organization=$($env:ADO_ORG)" ` + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/AzureDevOps/aadauth/complete?organization=$($env:ADO_ORG)" ` -Method Post -Headers $headers -Body $body -ContentType "application/json" Write-Host " ok" } catch { @@ -1028,7 +1028,7 @@ if ($DpTokenAvailable) { try { $token = Get-DpToken $headers = @{ Authorization = "Bearer $token" } - $null = Invoke-RestMethod -Uri "$AgentEndpoint/api/v1/AzureDevOps/auth/mi?organization=$($env:ADO_ORG)" ` + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/AzureDevOps/auth/mi?organization=$($env:ADO_ORG)" ` -Method Post -Headers $headers Write-Host " ok" } catch { @@ -1047,7 +1047,7 @@ if ($DpTokenAvailable) { if ($token) { try { $headers = @{ Authorization = "Bearer $token" } - $ghStatus = Invoke-RestMethod -Uri "$AgentEndpoint/api/v1/Github/auth/status" -Headers $headers + $ghStatus = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/Github/auth/status" -Headers $headers $ghConfigured = ($ghStatus.isConfigured -eq $true) -or ($ghStatus.hosts[0].isConfigured -eq $true) } catch { } } @@ -1076,7 +1076,7 @@ if ($DpTokenAvailable) { Authorization = "Bearer $token" "Content-Type" = "application/json" } - $null = Invoke-RestMethod -Uri "$AgentEndpoint/api/v2/extendedAgent/connectors/github" ` + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/extendedAgent/connectors/github" ` -Method Put -Headers $headers -Body $connBody -ContentType "application/json" Write-Host " ok connector/github (GitHubOAuth, identity=$($ident.Split('/')[-1]))" } catch { @@ -1106,7 +1106,7 @@ if ($DpTokenAvailable) { } | ConvertTo-Json -Compress -Depth 10 $encodedRname = [uri]::EscapeDataString($rname) try { - $null = Invoke-RestMethod -Uri "$AgentEndpoint/api/v2/repos/$encodedRname" ` + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/repos/$encodedRname" ` -Method Put -Headers $headers -Body $rbody -ContentType "application/json" Write-Host " ok repo/$rname ($rurl)" } catch { @@ -1122,7 +1122,7 @@ if ($DpTokenAvailable) { if ($token) { try { $headers = @{ Authorization = "Bearer $token" } - $ghConfig = Invoke-RestMethod -Uri "$AgentEndpoint/api/v1/Github/config" -Headers $headers + $ghConfig = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/Github/config" -Headers $headers $oauthUrl = if ($ghConfig.oAuthUrl) { $ghConfig.oAuthUrl } elseif ($ghConfig.OAuthUrl) { $ghConfig.OAuthUrl } else { $null } } catch { } } @@ -1138,7 +1138,7 @@ if ($DpTokenAvailable) { try { $token = Get-DpToken $headers = @{ Authorization = "Bearer $token" } - $ghCheck = Invoke-RestMethod -Uri "$AgentEndpoint/api/v1/Github/auth/status" -Headers $headers + $ghCheck = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/Github/auth/status" -Headers $headers if ($ghCheck.isConfigured -eq $true -or ($ghCheck.hosts -and $ghCheck.hosts[0].isConfigured -eq $true)) { Write-Host " GitHub authorized!" $authOk = $true @@ -1164,7 +1164,7 @@ if ($DpTokenAvailable) { properties = @{ dataConnectorType = "GitHubOAuth"; dataSource = "github-oauth"; identity = $ident } } | ConvertTo-Json -Compress -Depth 10 try { - $null = Invoke-RestMethod -Uri "$AgentEndpoint/api/v2/extendedAgent/connectors/github" ` + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/extendedAgent/connectors/github" ` -Method Put -Headers $headers -Body $connBody -ContentType "application/json" Write-Host " ok connector/github" } catch { @@ -1185,7 +1185,7 @@ if ($DpTokenAvailable) { } | ConvertTo-Json -Compress -Depth 10 $encodedRname = [uri]::EscapeDataString($rname) try { - $null = Invoke-RestMethod -Uri "$AgentEndpoint/api/v2/repos/$encodedRname" ` + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/repos/$encodedRname" ` -Method Put -Headers $headers -Body $rbody -ContentType "application/json" Write-Host " ok repo/$rname" } catch { From 7721b1db2345f3ffab500fb2236cc599846c9083 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 16:41:27 -0700 Subject: [PATCH 13/18] fix: pre-declare $errs for PS 7.6 compat; OAuth detect via JSON match; persist extras.json; Apply-Extras -ConfigDir --- .github/workflows/validate-templates.yml | 2 +- sreagent-templates/bicep/Apply-Extras.ps1 | 22 +++++++++++++++++++--- sreagent-templates/bicep/apply-extras.sh | 15 +++++++++++++-- sreagent-templates/bin/ps/Deploy-Agent.ps1 | 6 ++++++ 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/.github/workflows/validate-templates.yml b/.github/workflows/validate-templates.yml index 835febd7f..9e8b0a7d9 100644 --- a/.github/workflows/validate-templates.yml +++ b/.github/workflows/validate-templates.yml @@ -82,7 +82,7 @@ jobs: echo "Checking PowerShell scripts..." errors=0 for f in bin/ps/*.ps1; do - result=$(pwsh -NoProfile -Command "[System.Management.Automation.Language.Parser]::ParseFile('$f', [ref]\$null, [ref]\$errs); if(\$errs.Count -gt 0){\$errs | ForEach-Object { \$_.Message }}" 2>&1) + result=$(pwsh -NoProfile -Command "\$errs=\$null; [System.Management.Automation.Language.Parser]::ParseFile('$f', [ref]\$null, [ref]\$errs); if(\$errs -and \$errs.Count -gt 0){\$errs | ForEach-Object { \$_.Message }}" 2>&1) if [[ -n "$result" && "$result" != *"InvalidOperation"* ]]; then echo "❌ $f: $result" errors=$((errors + 1)) diff --git a/sreagent-templates/bicep/Apply-Extras.ps1 b/sreagent-templates/bicep/Apply-Extras.ps1 index e7892321a..18dfa9446 100644 --- a/sreagent-templates/bicep/Apply-Extras.ps1 +++ b/sreagent-templates/bicep/Apply-Extras.ps1 @@ -53,7 +53,10 @@ param( [string]$Subscription, [Parameter(Mandatory)][string]$ResourceGroup, [Parameter(Mandatory)][string]$AgentName, - [string]$ExtrasFile = "extras.parameters.json", + # Either supply a pre-assembled extras JSON OR a config directory — Apply-Extras + # will auto-assemble from the directory if ExtrasFile is not found. + [string]$ExtrasFile = "", + [string]$ConfigDir = "", [switch]$Force ) @@ -73,8 +76,20 @@ if (Test-Path $PrereqScript) { } } +# ── Auto-assemble from ConfigDir if ExtrasFile not supplied/found ─────────── +if (($ExtrasFile -eq "" -or -not (Test-Path $ExtrasFile)) -and $ConfigDir -ne "" -and (Test-Path $ConfigDir -PathType Container)) { + Write-Host "No extras file supplied — assembling from config dir: $ConfigDir" + $AssembleScript = Join-Path $PSScriptRoot 'Assemble-Agent.ps1' + $AssembleTmp = Join-Path ([System.IO.Path]::GetTempPath()) "assembled-$(New-Guid)" + & $AssembleScript -ConfigDir $ConfigDir -Output $AssembleTmp + $ExtrasFile = "${AssembleTmp}.extras.json" +} elseif ($ExtrasFile -eq "") { + # Default: look for .extras.json next to the script caller's cwd + $ExtrasFile = "extras.parameters.json" +} + if (-not (Test-Path $ExtrasFile)) { - Write-Error "extras file not found: $ExtrasFile" + Write-Error "extras file not found: $ExtrasFile`nTip: pass -ConfigDir to auto-assemble." return } @@ -1139,7 +1154,8 @@ if ($DpTokenAvailable) { $token = Get-DpToken $headers = @{ Authorization = "Bearer $token" } $ghCheck = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/Github/auth/status" -Headers $headers - if ($ghCheck.isConfigured -eq $true -or ($ghCheck.hosts -and $ghCheck.hosts[0].isConfigured -eq $true)) { + $ghJson = $ghCheck | ConvertTo-Json -Depth 10 -Compress + if ($ghJson -match '"isConfigured"\s*:\s*true') { Write-Host " GitHub authorized!" $authOk = $true break diff --git a/sreagent-templates/bicep/apply-extras.sh b/sreagent-templates/bicep/apply-extras.sh index 6584a8ce8..1ad80f6c3 100755 --- a/sreagent-templates/bicep/apply-extras.sh +++ b/sreagent-templates/bicep/apply-extras.sh @@ -30,7 +30,9 @@ # ADO — set $ADO_PAT, $ADO_USE_AAD=1, or $ADO_USE_MI=1 (with $ADO_ORG). # # Usage: -# ./apply-extras.sh [extras-file] +# ./apply-extras.sh [extras-file-or-config-dir] +# +# If the 4th argument is a directory (agent config dir), extras are auto-assembled from it. set -euo pipefail @@ -41,7 +43,16 @@ FILE="${4:-extras.parameters.json}" FORCE="" for arg in "$@"; do [[ "$arg" == "--force" ]] && FORCE="true"; done -[[ -f "$FILE" ]] || { echo "extras file not found: $FILE" >&2; exit 1; } +# Auto-assemble if a config directory was passed instead of a file +if [[ -d "$FILE" ]]; then + CONFIG_DIR="$FILE" + ASSEMBLE_TMP="$(mktemp -d)/assembled" + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + bash "${SCRIPT_DIR}/assemble-agent.sh" "$CONFIG_DIR" --output "$ASSEMBLE_TMP" + FILE="${ASSEMBLE_TMP}.extras.json" +fi + +[[ -f "$FILE" ]] || { echo "extras file not found: $FILE (pass a config dir or pre-assembled extras.json)" >&2; exit 1; } command -v jq >/dev/null || { echo "jq is required" >&2; exit 1; } command -v tar >/dev/null || { echo "tar is required" >&2; exit 1; } command -v curl >/dev/null || { echo "curl is required" >&2; exit 1; } diff --git a/sreagent-templates/bin/ps/Deploy-Agent.ps1 b/sreagent-templates/bin/ps/Deploy-Agent.ps1 index 7b1dcd05b..4d55c94d6 100644 --- a/sreagent-templates/bin/ps/Deploy-Agent.ps1 +++ b/sreagent-templates/bin/ps/Deploy-Agent.ps1 @@ -172,6 +172,12 @@ if ($IsDirectory) { $ExtrasFile = "${AssembleOut}.extras.json" $CleanupFiles += $ParametersFile, $ExtrasFile, (Split-Path $AssembleTmp -Parent) + # Copy extras.json into InputPath so it survives cleanup and can be re-used + # (e.g. re-running Apply-Extras standalone without a full re-deploy) + $AgentNameForExtras = (Get-Item $InputPath).Name + $PersistedExtras = Join-Path $InputPath "${AgentNameForExtras}.extras.json" + Copy-Item $ExtrasFile $PersistedExtras -Force + Write-Host '' } elseif (Test-Path $InputPath -PathType Leaf) { $ParametersFile = $InputPath From e054af1a58bfdd6ca70f6f36dbbddb9fc95e57d1 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 17:02:06 -0700 Subject: [PATCH 14/18] fix: poll /api/v1/Github/config instead of non-existent /auth/status endpoint --- sreagent-templates/bicep/Apply-Extras.ps1 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sreagent-templates/bicep/Apply-Extras.ps1 b/sreagent-templates/bicep/Apply-Extras.ps1 index 18dfa9446..9d135fa26 100644 --- a/sreagent-templates/bicep/Apply-Extras.ps1 +++ b/sreagent-templates/bicep/Apply-Extras.ps1 @@ -1153,9 +1153,12 @@ if ($DpTokenAvailable) { try { $token = Get-DpToken $headers = @{ Authorization = "Bearer $token" } - $ghCheck = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/Github/auth/status" -Headers $headers - $ghJson = $ghCheck | ConvertTo-Json -Depth 10 -Compress - if ($ghJson -match '"isConfigured"\s*:\s*true') { + # Poll /config: before OAuth it returns {oAuthUrl:"..."}; after OAuth oAuthUrl is absent + $ghCfg = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/Github/config" -Headers $headers + $cfgJson = $ghCfg | ConvertTo-Json -Depth 10 -Compress + $hasOAuthUrl = $cfgJson -match '"oAuthUrl"' + $isConfigured = $cfgJson -match '"isConfigured"\s*:\s*true' + if ($isConfigured -or -not $hasOAuthUrl) { Write-Host " GitHub authorized!" $authOk = $true break From 92b9fc167dcd10285265afa70d133ae9dd55b255 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 17:05:02 -0700 Subject: [PATCH 15/18] fix: detect GitHub OAuth by attempting connector PUT instead of polling non-existent /auth/status --- sreagent-templates/bicep/Apply-Extras.ps1 | 41 ++++++++++------------- sreagent-templates/bicep/apply-extras.sh | 19 +++++------ 2 files changed, 26 insertions(+), 34 deletions(-) diff --git a/sreagent-templates/bicep/Apply-Extras.ps1 b/sreagent-templates/bicep/Apply-Extras.ps1 index 9d135fa26..d9bee1a11 100644 --- a/sreagent-templates/bicep/Apply-Extras.ps1 +++ b/sreagent-templates/bicep/Apply-Extras.ps1 @@ -1148,21 +1148,26 @@ if ($DpTokenAvailable) { Write-Host "" Write-Host " Waiting for GitHub authorization (Ctrl-C to skip)..." $authOk = $false + $ident = if ($AgentUami) { $AgentUami } else { "SystemAssigned" } + $connBody = @{ + name = "github"; type = "AgentConnector" + properties = @{ dataConnectorType = "GitHubOAuth"; dataSource = "github-oauth"; identity = $ident } + } | ConvertTo-Json -Compress -Depth 10 for ($attempt = 1; $attempt -le 24; $attempt++) { Start-Sleep -Seconds 10 try { $token = Get-DpToken - $headers = @{ Authorization = "Bearer $token" } - # Poll /config: before OAuth it returns {oAuthUrl:"..."}; after OAuth oAuthUrl is absent - $ghCfg = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/Github/config" -Headers $headers - $cfgJson = $ghCfg | ConvertTo-Json -Depth 10 -Compress - $hasOAuthUrl = $cfgJson -match '"oAuthUrl"' - $isConfigured = $cfgJson -match '"isConfigured"\s*:\s*true' - if ($isConfigured -or -not $hasOAuthUrl) { - Write-Host " GitHub authorized!" - $authOk = $true - break + $headers = @{ + Authorization = "Bearer $token" + "Content-Type" = "application/json" } + # Try creating the connector — succeeds once OAuth is done, throws until then + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/extendedAgent/connectors/github" ` + -Method Put -Headers $headers -Body $connBody -ContentType "application/json" + Write-Host " GitHub authorized!" + Write-Host " ok connector/github" + $authOk = $true + break } catch { } Write-Host " ... waiting ($($attempt * 10)/240s)" -NoNewline Write-Host "`r" -NoNewline @@ -1170,25 +1175,13 @@ if ($DpTokenAvailable) { Write-Host "" if ($authOk) { - # Re-enter the OAuth-done path: create connector + repos - Write-Host "-- Wiring GitHub connector + repos --" - $ident = if ($AgentUami) { $AgentUami } else { "SystemAssigned" } + # Connector already created in polling loop — wire repos only + Write-Host "-- Wiring GitHub repos --" $token = Get-DpToken $headers = @{ Authorization = "Bearer $token" "Content-Type" = "application/json" } - $connBody = @{ - name = "github"; type = "AgentConnector" - properties = @{ dataConnectorType = "GitHubOAuth"; dataSource = "github-oauth"; identity = $ident } - } | ConvertTo-Json -Compress -Depth 10 - try { - $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/extendedAgent/connectors/github" ` - -Method Put -Headers $headers -Body $connBody -ContentType "application/json" - Write-Host " ok connector/github" - } catch { - Write-Host " FAILED connector/github" - } foreach ($repo in $repos) { $rname = $repo.name $rurl = $repo.spec.url diff --git a/sreagent-templates/bicep/apply-extras.sh b/sreagent-templates/bicep/apply-extras.sh index 1ad80f6c3..912017080 100755 --- a/sreagent-templates/bicep/apply-extras.sh +++ b/sreagent-templates/bicep/apply-extras.sh @@ -911,14 +911,18 @@ if [[ ${#oauth_repos[@]} -gt 0 ]]; then echo " 2. Sign in to GitHub and approve the SRE Agent app." echo echo " Waiting for GitHub authorization (Ctrl-C to skip)..." + if [[ -z "$AGENT_UAMI" ]]; then IDENT="SystemAssigned"; else IDENT="$AGENT_UAMI"; fi + conn_body=$(jq -nc --arg id "$IDENT" '{name:"github",type:"AgentConnector",properties:{dataConnectorType:"GitHubOAuth",dataSource:"github-oauth",identity:$id}}') auth_ok=false for attempt in $(seq 1 24); do sleep 10 TOKEN=$(_dp_token 2>/dev/null || true) - GH_CHECK=$(curl -sS -H "Authorization: Bearer ${TOKEN}" \ - "${AGENT_ENDPOINT}/api/v1/Github/auth/status" 2>/dev/null || echo '{}') - if echo "$GH_CHECK" | jq -e '.isConfigured // .hosts[0].isConfigured' 2>/dev/null | grep -q 'true'; then + # Try creating the connector — succeeds once OAuth is done, fails until then + if curl -sS -f -X PUT "${AGENT_ENDPOINT}/api/v2/extendedAgent/connectors/github" \ + -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \ + --data "$conn_body" >/dev/null 2>&1; then echo " GitHub authorized!" + echo " ok connector/github" auth_ok=true break fi @@ -927,14 +931,9 @@ if [[ ${#oauth_repos[@]} -gt 0 ]]; then echo if [[ "$auth_ok" == "true" ]]; then - # Re-enter the OAuth-done path: create connector + repos - echo "── Wiring GitHub connector + repos ──" - if [[ -z "$AGENT_UAMI" ]]; then IDENT="SystemAssigned"; else IDENT="$AGENT_UAMI"; fi + # Connector already created in polling loop — wire repos only + echo "── Wiring GitHub repos ──" TOKEN=$(_dp_token) - body=$(jq -nc --arg id "$IDENT" '{name:"github",type:"AgentConnector",properties:{dataConnectorType:"GitHubOAuth",dataSource:"github-oauth",identity:$id}}') - curl -sS -f -X PUT "${AGENT_ENDPOINT}/api/v2/extendedAgent/connectors/github" \ - -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" --data "$body" >/dev/null && \ - echo " ok connector/github" || echo " FAILED connector/github" count=$(jq '.repos // [] | length' "$FILE") for i in $(seq 0 $((count - 1))); do rname=$(jq -r --argjson i "$i" '.repos[$i].name' "$FILE") From c1b01a472ff8245217ccf8e573bdd0db127785e2 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Fri, 15 May 2026 17:49:01 -0700 Subject: [PATCH 16/18] fix: replace bare jq calls with Invoke-Jq in Verify-Agent.ps1 --- sreagent-templates/bin/ps/Verify-Agent.ps1 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sreagent-templates/bin/ps/Verify-Agent.ps1 b/sreagent-templates/bin/ps/Verify-Agent.ps1 index 1f28df28d..40bb686aa 100644 --- a/sreagent-templates/bin/ps/Verify-Agent.ps1 +++ b/sreagent-templates/bin/ps/Verify-Agent.ps1 @@ -184,18 +184,18 @@ $Props = $AgentJson | Invoke-Jq -Compact -Filter '{ }' Add-Check 'Agent exists' 'yes' 'yes' -Add-Check 'Access level' ($Props | jq -r '.accessLevel') (Get-Exp '.agent.accessLevel') -Add-Check 'Action mode' ($Props | jq -r '.mode') (Get-Exp '.agent.actionMode') -Add-Check 'Upgrade channel' ($Props | jq -r '.upgradeChannel') (Get-Exp '.agent.upgradeChannel') -Add-Check 'Model provider' ($Props | jq -r '.modelProvider') (Get-Exp '.agent.defaultModelProvider') -Add-Check 'Incident platform' ($Props | jq -r '.incidentPlatform') (Get-Exp '.agent.incidentPlatform') +Add-Check 'Access level' ($Props | Invoke-Jq -Raw -Filter '.accessLevel') (Get-Exp '.agent.accessLevel') +Add-Check 'Action mode' ($Props | Invoke-Jq -Raw -Filter '.mode') (Get-Exp '.agent.actionMode') +Add-Check 'Upgrade channel' ($Props | Invoke-Jq -Raw -Filter '.upgradeChannel') (Get-Exp '.agent.upgradeChannel') +Add-Check 'Model provider' ($Props | Invoke-Jq -Raw -Filter '.modelProvider') (Get-Exp '.agent.defaultModelProvider') +Add-Check 'Incident platform' ($Props | Invoke-Jq -Raw -Filter '.incidentPlatform') (Get-Exp '.agent.incidentPlatform') # ─────────────────────────── Connectors (ARM) ─────────────────────────── $Connectors = Invoke-Arm '/DataConnectors' -$ConnCt = $Connectors | jq '.value | length' +$ConnCt = $Connectors | Invoke-Jq -Filter '.value | length' $ConnHealthy = $Connectors | Invoke-Jq -Filter '[.value[] | select(.properties.provisioningState == "Succeeded")] | length' -$ConnNames = ($Connectors | jq -r '.value[].name' 2>$null | Sort-Object) -join ',' +$ConnNames = ($Connectors | Invoke-Jq -Raw -Filter '.value[].name' | Sort-Object) -join ',' $ExpConnCt = Get-Exp '.connectors | length' $ExpConnNames = Get-ExpList '[.connectors[].name]' @@ -226,9 +226,9 @@ if ($ExpSkillNames) { # ─────────────────────────── Subagents ─────────────────────────── $Subagents = Invoke-Dp '/api/v2/extendedAgent/agents' -$SaCt = $Subagents | jq '.value | length' 2>$null +$SaCt = $Subagents | Invoke-Jq -Filter '.value | length' if (-not $SaCt) { $SaCt = '0' } -$SaNames = ($Subagents | jq -r '.value[].name' 2>$null | Sort-Object) -join ',' +$SaNames = ($Subagents | Invoke-Jq -Raw -Filter '.value[].name' | Sort-Object) -join ',' $ExpSaCt = Get-Exp '.subagents | length' $ExpSaNames = Get-ExpList '.subagents' From 72546eaf249288c37cf7563998f64d4176a91516 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Mon, 18 May 2026 16:27:47 -0700 Subject: [PATCH 17/18] fix: Export empty-string args, GitHub OAuth stale-auth fallback, verify JSON validation, e2e test scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Export-Agent.ps1: pad empty string args for jq (PS drops ''), add tarball download retry with token refresh - Apply-Extras.ps1: GitHub OAuth fast-path now verifies connector health; wait loop checks auth/status instead of connector PUT; stale auth falls through to OAuth wait - apply-extras.sh: OAuth wait loop checks auth/status instead of connector PUT success - Verify-Agent.ps1: validate data-plane responses are JSON before piping to jq - verify-agent.sh: same JSON validation in dp_get() - tests/e2e-ps/: 12 e2e test scripts (4 recipes × 3 backends) + run-all orchestrator --- sreagent-templates/bicep/Apply-Extras.ps1 | 183 +++++++++--------- sreagent-templates/bicep/apply-extras.sh | 13 +- sreagent-templates/bin/ps/Export-Agent.ps1 | 56 ++++-- sreagent-templates/bin/ps/Verify-Agent.ps1 | 10 +- sreagent-templates/bin/verify-agent.sh | 11 +- .../tests/e2e-ps/run-all-ps-e2e.sh | 107 ++++++++++ .../tests/e2e-ps/test-azmon-azd-ps.sh | 57 ++++++ .../tests/e2e-ps/test-azmon-bicep-ps.sh | 49 +++++ .../tests/e2e-ps/test-azmon-tf-ps.sh | 49 +++++ .../tests/e2e-ps/test-dt-azd-ps.sh | 58 ++++++ .../tests/e2e-ps/test-dt-bicep-ps.sh | 50 +++++ .../tests/e2e-ps/test-dt-tf-ps.sh | 50 +++++ .../tests/e2e-ps/test-min-azd-ps.sh | 54 ++++++ .../tests/e2e-ps/test-min-bicep-ps.sh | 46 +++++ .../tests/e2e-ps/test-min-tf-ps.sh | 46 +++++ .../tests/e2e-ps/test-pd-azd-ps.sh | 56 ++++++ .../tests/e2e-ps/test-pd-bicep-ps.sh | 48 +++++ .../tests/e2e-ps/test-pd-tf-ps.sh | 48 +++++ 18 files changed, 870 insertions(+), 121 deletions(-) create mode 100755 sreagent-templates/tests/e2e-ps/run-all-ps-e2e.sh create mode 100755 sreagent-templates/tests/e2e-ps/test-azmon-azd-ps.sh create mode 100755 sreagent-templates/tests/e2e-ps/test-azmon-bicep-ps.sh create mode 100755 sreagent-templates/tests/e2e-ps/test-azmon-tf-ps.sh create mode 100755 sreagent-templates/tests/e2e-ps/test-dt-azd-ps.sh create mode 100755 sreagent-templates/tests/e2e-ps/test-dt-bicep-ps.sh create mode 100755 sreagent-templates/tests/e2e-ps/test-dt-tf-ps.sh create mode 100755 sreagent-templates/tests/e2e-ps/test-min-azd-ps.sh create mode 100755 sreagent-templates/tests/e2e-ps/test-min-bicep-ps.sh create mode 100755 sreagent-templates/tests/e2e-ps/test-min-tf-ps.sh create mode 100755 sreagent-templates/tests/e2e-ps/test-pd-azd-ps.sh create mode 100755 sreagent-templates/tests/e2e-ps/test-pd-bicep-ps.sh create mode 100755 sreagent-templates/tests/e2e-ps/test-pd-tf-ps.sh diff --git a/sreagent-templates/bicep/Apply-Extras.ps1 b/sreagent-templates/bicep/Apply-Extras.ps1 index d9bee1a11..50eb30cb3 100644 --- a/sreagent-templates/bicep/Apply-Extras.ps1 +++ b/sreagent-templates/bicep/Apply-Extras.ps1 @@ -1067,24 +1067,26 @@ if ($DpTokenAvailable) { } catch { } } - if ($ghConfigured -or $env:GITHUB_PAT) { - # OAuth (or PAT) is in place — wire the connector + repos - Write-Host "-- Wiring GitHub connector + repos --" - $ident = if ($AgentUami) { $AgentUami } else { - Write-Host " WARN: agent has no user-assigned MI; falling back to SystemAssigned." - "SystemAssigned" + # Shared identity + connector body (used in both fast-path and OAuth wait) + $ident = if ($AgentUami) { $AgentUami } else { + Write-Host " WARN: agent has no user-assigned MI; falling back to SystemAssigned." + "SystemAssigned" + } + $connBody = @{ + name = "github" + type = "AgentConnector" + properties = @{ + dataConnectorType = "GitHubOAuth" + dataSource = "github-oauth" + identity = $ident } + } | ConvertTo-Json -Compress -Depth 10 - # 1) Create the GitHubOAuth connector - $connBody = @{ - name = "github" - type = "AgentConnector" - properties = @{ - dataConnectorType = "GitHubOAuth" - dataSource = "github-oauth" - identity = $ident - } - } | ConvertTo-Json -Compress -Depth 10 + $connectorOk = $false + + # Fast path: if auth/status says configured (or PAT), try the connector PUT immediately + if ($ghConfigured -or $env:GITHUB_PAT) { + Write-Host "-- Wiring GitHub connector + repos --" try { $token = Get-DpToken $headers = @{ @@ -1093,47 +1095,33 @@ if ($DpTokenAvailable) { } $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/extendedAgent/connectors/github" ` -Method Put -Headers $headers -Body $connBody -ContentType "application/json" - Write-Host " ok connector/github (GitHubOAuth, identity=$($ident.Split('/')[-1]))" - } catch { - Write-Host " FAILED - PUT /api/v2/extendedAgent/connectors/github" - } - - # 2) Attach each repo - foreach ($repo in $repos) { - $rname = $repo.name - $rurl = $repo.spec.url - # Normalize short "org/repo" to full URL (API requires https://...) - if ($rurl -and $rurl -notmatch '^https?://' -and $rurl -match '/') { - $rurl = "https://github.com/$rurl" - } - $rtypeIn = if ($repo.spec.type) { $repo.spec.type } else { "github" } - $rtype = switch -Regex ($rtypeIn.ToLower()) { - '^(ado|azuredevops|azure-devops)$' { "AzureDevOps" } - default { "GitHub" } - } - $rdesc = if ($repo.spec.description) { $repo.spec.description } else { "" } - $rProps = @{ url = $rurl; type = $rtype } - if ($rdesc) { $rProps.description = $rdesc } - $rbody = @{ - name = $rname - type = "CodeRepo" - properties = $rProps - } | ConvertTo-Json -Compress -Depth 10 - $encodedRname = [uri]::EscapeDataString($rname) + # Verify the connector is actually healthy (not just metadata) + Start-Sleep -Seconds 3 try { - $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/repos/$encodedRname" ` - -Method Put -Headers $headers -Body $rbody -ContentType "application/json" - Write-Host " ok repo/$rname ($rurl)" + $connCheck = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/extendedAgent/connectors/github" ` + -Method Get -Headers @{ Authorization = "Bearer $token" } + $provState = $connCheck.properties.provisioningState + if ($provState -eq 'Succeeded') { + Write-Host " ok connector/github (GitHubOAuth, identity=$($ident.Split('/')[-1]))" + $connectorOk = $true + } else { + Write-Host " WARN: connector created but state=$provState — falling back to OAuth wait..." + } } catch { - Write-Host " FAILED - PUT /api/v2/repos/$rname (try the portal Repos blade)" + Write-Host " ok connector/github (GitHubOAuth, identity=$($ident.Split('/')[-1]))" + $connectorOk = $true } + } catch { + Write-Host " WARN: connector PUT failed (stale auth?) — falling back to OAuth wait..." } - Write-Host "" - } else { - # OAuth not done — print sign-in URL + } + + # OAuth wait: if connector not yet created, show URL and poll until user completes auth + if (-not $connectorOk -and -not $env:GITHUB_PAT) { Write-Host "-- GitHub OAuth sign-in required --" Write-Host "Repos waiting: $($oauthRepos -join ' ')" $oauthUrl = $null + try { $token = Get-DpToken } catch { $token = $null } if ($token) { try { $headers = @{ Authorization = "Bearer $token" } @@ -1147,12 +1135,6 @@ if ($DpTokenAvailable) { Write-Host " 2. Sign in to GitHub and approve the SRE Agent app." Write-Host "" Write-Host " Waiting for GitHub authorization (Ctrl-C to skip)..." - $authOk = $false - $ident = if ($AgentUami) { $AgentUami } else { "SystemAssigned" } - $connBody = @{ - name = "github"; type = "AgentConnector" - properties = @{ dataConnectorType = "GitHubOAuth"; dataSource = "github-oauth"; identity = $ident } - } | ConvertTo-Json -Compress -Depth 10 for ($attempt = 1; $attempt -le 24; $attempt++) { Start-Sleep -Seconds 10 try { @@ -1161,50 +1143,23 @@ if ($DpTokenAvailable) { Authorization = "Bearer $token" "Content-Type" = "application/json" } - # Try creating the connector — succeeds once OAuth is done, throws until then - $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/extendedAgent/connectors/github" ` - -Method Put -Headers $headers -Body $connBody -ContentType "application/json" - Write-Host " GitHub authorized!" - Write-Host " ok connector/github" - $authOk = $true - break + # Check auth/status — only trust isConfigured, not connector PUT success + $ghCheck = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v1/Github/auth/status" -Headers $headers + $isAuth = ($ghCheck.isConfigured -eq $true) -or ($ghCheck.hosts -and $ghCheck.hosts[0].isConfigured -eq $true) + if ($isAuth) { + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/extendedAgent/connectors/github" ` + -Method Put -Headers $headers -Body $connBody -ContentType "application/json" + Write-Host " GitHub authorized!" + Write-Host " ok connector/github" + $connectorOk = $true + break + } } catch { } Write-Host " ... waiting ($($attempt * 10)/240s)" -NoNewline Write-Host "`r" -NoNewline } Write-Host "" - - if ($authOk) { - # Connector already created in polling loop — wire repos only - Write-Host "-- Wiring GitHub repos --" - $token = Get-DpToken - $headers = @{ - Authorization = "Bearer $token" - "Content-Type" = "application/json" - } - foreach ($repo in $repos) { - $rname = $repo.name - $rurl = $repo.spec.url - # Normalize short "org/repo" to full URL (API requires https://...) - if ($rurl -and $rurl -notmatch '^https?://' -and $rurl -match '/') { - $rurl = "https://github.com/$rurl" - } - $rtypeIn = if ($repo.spec.type) { $repo.spec.type } else { "github" } - $rtype = if ($rtypeIn.ToLower() -match '^(ado|azuredevops|azure-devops)$') { "AzureDevOps" } else { "GitHub" } - $rbody = @{ - name = $rname; type = "CodeRepo" - properties = @{ url = $rurl; type = $rtype } - } | ConvertTo-Json -Compress -Depth 10 - $encodedRname = [uri]::EscapeDataString($rname) - try { - $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/repos/$encodedRname" ` - -Method Put -Headers $headers -Body $rbody -ContentType "application/json" - Write-Host " ok repo/$rname" - } catch { - Write-Host " FAILED repo/$rname" - } - } - } else { + if (-not $connectorOk) { Write-Host " Timed out. Re-run Apply-Extras after authorizing." Write-Host " Headless alternative: `$env:GITHUB_PAT='ghp_xxx' && re-run" } @@ -1212,6 +1167,44 @@ if ($DpTokenAvailable) { Write-Host " Could not fetch OAuth URL from $AgentEndpoint/api/v1/Github/config." Write-Host " Fallback: Azure portal -> agent -> Repos -> 'Authorize' next to each repo." } + } + + # Wire repos (only if connector succeeded) + if ($connectorOk) { + Write-Host "-- Wiring GitHub repos --" + $token = Get-DpToken + $headers = @{ + Authorization = "Bearer $token" + "Content-Type" = "application/json" + } + foreach ($repo in $repos) { + $rname = $repo.name + $rurl = $repo.spec.url + if ($rurl -and $rurl -notmatch '^https?://' -and $rurl -match '/') { + $rurl = "https://github.com/$rurl" + } + $rtypeIn = if ($repo.spec.type) { $repo.spec.type } else { "github" } + $rtype = switch -Regex ($rtypeIn.ToLower()) { + '^(ado|azuredevops|azure-devops)$' { "AzureDevOps" } + default { "GitHub" } + } + $rdesc = if ($repo.spec.description) { $repo.spec.description } else { "" } + $rProps = @{ url = $rurl; type = $rtype } + if ($rdesc) { $rProps.description = $rdesc } + $rbody = @{ + name = $rname + type = "CodeRepo" + properties = $rProps + } | ConvertTo-Json -Compress -Depth 10 + $encodedRname = [uri]::EscapeDataString($rname) + try { + $null = Invoke-RestMethod -TimeoutSec 30 -Uri "$AgentEndpoint/api/v2/repos/$encodedRname" ` + -Method Put -Headers $headers -Body $rbody -ContentType "application/json" + Write-Host " ok repo/$rname ($rurl)" + } catch { + Write-Host " FAILED - PUT /api/v2/repos/$rname (try the portal Repos blade)" + } + } Write-Host "" } } diff --git a/sreagent-templates/bicep/apply-extras.sh b/sreagent-templates/bicep/apply-extras.sh index 912017080..9093ebae5 100755 --- a/sreagent-templates/bicep/apply-extras.sh +++ b/sreagent-templates/bicep/apply-extras.sh @@ -917,10 +917,15 @@ if [[ ${#oauth_repos[@]} -gt 0 ]]; then for attempt in $(seq 1 24); do sleep 10 TOKEN=$(_dp_token 2>/dev/null || true) - # Try creating the connector — succeeds once OAuth is done, fails until then - if curl -sS -f -X PUT "${AGENT_ENDPOINT}/api/v2/extendedAgent/connectors/github" \ - -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \ - --data "$conn_body" >/dev/null 2>&1; then + # Check auth/status — only trust isConfigured, not connector PUT success + GH_CHECK=$(curl -sS -H "Authorization: Bearer ${TOKEN}" \ + "${AGENT_ENDPOINT}/api/v1/Github/auth/status" 2>/dev/null || echo '{}') + IS_AUTH=$(echo "$GH_CHECK" | jq -r '.isConfigured // .hosts[0].isConfigured // false') + if [[ "$IS_AUTH" == "true" ]]; then + # Auth confirmed — now create the connector + curl -sS -f -X PUT "${AGENT_ENDPOINT}/api/v2/extendedAgent/connectors/github" \ + -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \ + --data "$conn_body" >/dev/null 2>&1 || true echo " GitHub authorized!" echo " ok connector/github" auth_ok=true diff --git a/sreagent-templates/bin/ps/Export-Agent.ps1 b/sreagent-templates/bin/ps/Export-Agent.ps1 index b61276be9..6aa4c97d5 100644 --- a/sreagent-templates/bin/ps/Export-Agent.ps1 +++ b/sreagent-templates/bin/ps/Export-Agent.ps1 @@ -257,25 +257,34 @@ function Invoke-DpDownload { # ── Data-plane download tarball ── function Invoke-DpDownloadTarball { - param([string]$Path, [string]$DestDir, [string]$Label) - $token = Get-DpToken - $tmpfile = [System.IO.Path]::GetTempFileName() + '.tar.gz' + param([string]$Path, [string]$DestDir, [string]$Label, [int]$Retries = 3) $ok = $false - try { - curl -sS -f -H "Authorization: Bearer $token" -o $tmpfile "${AGENT_ENDPOINT}${Path}" 2>$null - if ($LASTEXITCODE -eq 0) { - if (-not (Test-Path $DestDir)) { New-Item -ItemType Directory -Path $DestDir -Force | Out-Null } - tar -xzf $tmpfile -C $DestDir 2>$null - $count = (Get-ChildItem -Path $DestDir -File -Recurse -ErrorAction SilentlyContinue | Measure-Object).Count - _log " Downloaded ${Label}: ${count} file(s) → ${DestDir}" - $ok = $true - } else { - _log " WARN: Could not download ${Label}" + for ($attempt = 1; $attempt -le $Retries; $attempt++) { + $token = Get-DpToken + $tmpfile = [System.IO.Path]::GetTempFileName() + '.tar.gz' + try { + curl -sS -f -H "Authorization: Bearer $token" -o $tmpfile "${AGENT_ENDPOINT}${Path}" 2>$null + if ($LASTEXITCODE -eq 0) { + if (-not (Test-Path $DestDir)) { New-Item -ItemType Directory -Path $DestDir -Force | Out-Null } + tar -xzf $tmpfile -C $DestDir 2>$null + $count = (Get-ChildItem -Path $DestDir -File -Recurse -ErrorAction SilentlyContinue | Measure-Object).Count + _log " Downloaded ${Label}: ${count} file(s) → ${DestDir}" + $ok = $true + break + } + } catch { } + finally { + Remove-Item $tmpfile -Force -ErrorAction SilentlyContinue + } + if ($attempt -lt $Retries) { + _log " Retry ${attempt}/${Retries} for ${Label} download..." + Start-Sleep -Seconds (5 * $attempt) + # Refresh token on retry + $script:DpTokenCache = '' } - } catch { - _log " WARN: Could not download ${Label}" - } finally { - Remove-Item $tmpfile -Force -ErrorAction SilentlyContinue + } + if (-not $ok) { + _log " WARN: Could not download ${Label} after ${Retries} attempts" } return $ok } @@ -1165,13 +1174,20 @@ $enableAIStr = if ($ENABLE_AI) { 'true' } else { 'false' } $enableLAWStr = if ($ENABLE_LAW) { 'true' } else { 'false' } $enableAzMonStr = if ($ENABLE_AZMON) { 'true' } else { 'false' } +# PowerShell drops empty-string arguments when calling native commands, which +# misaligns jq --arg pairs. Default to a single space so the arg is preserved; +# the values are only used when their toggle is true. +if ([string]::IsNullOrEmpty($AI_RESOURCE_ID)) { $AI_RESOURCE_ID = ' ' } +if ([string]::IsNullOrEmpty($AI_APP_ID)) { $AI_APP_ID = ' ' } +if ([string]::IsNullOrEmpty($LAW_RESOURCE_ID)) { $LAW_RESOURCE_ID = ' ' } + $CONNECTORS_ARRAY | Invoke-Jq -Filter '{ "toggles": { "enableAppInsightsConnector": ($enableAI | test("true")), - "appInsightsResourceId": $aiResId, - "appInsightsAppId": $aiAppId, + "appInsightsResourceId": ($aiResId | ltrimstr(" ")), + "appInsightsAppId": ($aiAppId | ltrimstr(" ")), "enableLogAnalyticsConnector": ($enableLAW | test("true")), - "lawResourceId": $lawResId, + "lawResourceId": ($lawResId | ltrimstr(" ")), "enableAzureMonitorConnector": ($enableAzMon | test("true")), "azureMonitorLookbackDays": ($azMonLookback | tonumber) }, diff --git a/sreagent-templates/bin/ps/Verify-Agent.ps1 b/sreagent-templates/bin/ps/Verify-Agent.ps1 index 40bb686aa..6785d36eb 100644 --- a/sreagent-templates/bin/ps/Verify-Agent.ps1 +++ b/sreagent-templates/bin/ps/Verify-Agent.ps1 @@ -114,7 +114,15 @@ if (-not $Token) { function Invoke-Dp { param([string]$Path) - (curl -sS "${Endpoint}${Path}" -H "Authorization: Bearer $Token" 2>$null) -join "`n" + $raw = (curl -sS "${Endpoint}${Path}" -H "Authorization: Bearer $Token" 2>$null) -join "`n" + # Validate response is JSON; return empty object/array fallback if not + if ($raw) { + try { + $null = $raw | jq -e 'type' 2>$null + if ($LASTEXITCODE -eq 0) { return $raw } + } catch { } + } + return '{}' } function Invoke-Arm { diff --git a/sreagent-templates/bin/verify-agent.sh b/sreagent-templates/bin/verify-agent.sh index 40fb653aa..5d8107ec2 100755 --- a/sreagent-templates/bin/verify-agent.sh +++ b/sreagent-templates/bin/verify-agent.sh @@ -68,7 +68,16 @@ if [[ -z "$TOKEN" ]]; then exit 1 fi -dp_get() { curl -sS "$ENDPOINT$1" -H "Authorization: Bearer $TOKEN" 2>/dev/null; } +dp_get() { + local raw + raw=$(curl -sS "$ENDPOINT$1" -H "Authorization: Bearer $TOKEN" 2>/dev/null) + # Validate JSON; return empty object if response is HTML/error + if echo "$raw" | jq -e 'type' >/dev/null 2>&1; then + echo "$raw" + else + echo '{}' + fi +} arm_get() { az rest -m GET --url "${ARM_BASE}$1?api-version=${API_VERSION}" -o json 2>/dev/null || echo "{}"; } PASS=0 diff --git a/sreagent-templates/tests/e2e-ps/run-all-ps-e2e.sh b/sreagent-templates/tests/e2e-ps/run-all-ps-e2e.sh new file mode 100755 index 000000000..91bb78b11 --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/run-all-ps-e2e.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash +# run-all-ps-e2e.sh — Run all 12 PS e2e tests (4 recipes × 3 backends) +# Run from sreagent-templates/ directory +# Usage: +# ./tests/e2e-ps/run-all-ps-e2e.sh # run all 12 tests +# ./tests/e2e-ps/run-all-ps-e2e.sh azmon # run only azmon tests +# ./tests/e2e-ps/run-all-ps-e2e.sh dt bicep # run dt-bicep only +# +# Requires: DT_TOKEN env var (for dynatrace tests) +set -uo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPORT="/tmp/e2e-ps-matrix-results.txt" +> "$REPORT" + +TOTAL_PASS=0; TOTAL_FAIL=0; TOTAL_SKIP=0 +RESULTS=() + +FILTER_RECIPE="${1:-}" +FILTER_BACKEND="${2:-}" + +TESTS=( + "test-azmon-bicep-ps.sh" + "test-azmon-tf-ps.sh" + "test-azmon-azd-ps.sh" + "test-pd-bicep-ps.sh" + "test-pd-tf-ps.sh" + "test-pd-azd-ps.sh" + "test-dt-bicep-ps.sh" + "test-dt-tf-ps.sh" + "test-dt-azd-ps.sh" + "test-min-bicep-ps.sh" + "test-min-tf-ps.sh" + "test-min-azd-ps.sh" +) + +log() { echo "$1" | tee -a "$REPORT"; } + +log "╔══════════════════════════════════════════════════════╗" +log "║ E2E PS Matrix — 4 recipes × 3 backends ║" +log "║ Started: $(date) ║" +log "╚══════════════════════════════════════════════════════╝" +log "" + +# Pre-flight: check DT_TOKEN for dt tests +if [[ -z "${DT_TOKEN:-}" ]]; then + log "⚠️ DT_TOKEN not set — dynatrace tests will be skipped" +fi + +for test in "${TESTS[@]}"; do + # Extract recipe and backend from filename: test-{recipe}-{backend}-ps.sh + recipe=$(echo "$test" | sed 's/test-//' | sed 's/-ps\.sh//' | rev | cut -d- -f2- | rev) + backend=$(echo "$test" | sed 's/test-//' | sed 's/-ps\.sh//' | rev | cut -d- -f1 | rev) + + # Apply filters + if [[ -n "$FILTER_RECIPE" && "$recipe" != *"$FILTER_RECIPE"* ]]; then + continue + fi + if [[ -n "$FILTER_BACKEND" && "$backend" != *"$FILTER_BACKEND"* ]]; then + continue + fi + + # Skip dt tests if no DT_TOKEN + if [[ "$recipe" == *"dt"* && -z "${DT_TOKEN:-}" ]]; then + log "⏭️ SKIP: $test (DT_TOKEN not set)" + RESULTS+=("SKIP: $test") + ((TOTAL_SKIP++)) + continue + fi + + log "────────────────────────────────────────" + log "▶ Running: $test" + log "────────────────────────────────────────" + + START_TIME=$(date +%s) + bash "$SCRIPT_DIR/$test" + RC=$? + END_TIME=$(date +%s) + DURATION=$((END_TIME - START_TIME)) + + if [[ $RC -eq 0 ]]; then + log "✅ PASS: $test (${DURATION}s)" + RESULTS+=("PASS: $test (${DURATION}s)") + ((TOTAL_PASS++)) + else + log "❌ FAIL: $test (rc=$RC, ${DURATION}s)" + RESULTS+=("FAIL: $test (rc=$RC, ${DURATION}s)") + ((TOTAL_FAIL++)) + fi + log "" +done + +log "" +log "╔══════════════════════════════════════════════════════╗" +log "║ FINAL RESULTS ║" +log "╠══════════════════════════════════════════════════════╣" +for r in "${RESULTS[@]}"; do + log "║ $r" +done +log "╠══════════════════════════════════════════════════════╣" +log "║ PASS: $TOTAL_PASS FAIL: $TOTAL_FAIL SKIP: $TOTAL_SKIP" +log "║ Finished: $(date)" +log "╚══════════════════════════════════════════════════════╝" +log "" +log "Full report: $REPORT" + +[[ $TOTAL_FAIL -eq 0 ]] && exit 0 || exit 1 diff --git a/sreagent-templates/tests/e2e-ps/test-azmon-azd-ps.sh b/sreagent-templates/tests/e2e-ps/test-azmon-azd-ps.sh new file mode 100755 index 000000000..58725cb45 --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/test-azmon-azd-ps.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# E2E: azmon-lawappinsights × azd +set -uo pipefail +cd "$(dirname "$0")/../.." + +pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ + -Recipe 'azmon-lawappinsights' \ + -NonInteractive \ + -Set @{ \ + agentName='azmon-azd-e2e'; \ + resourceGroup='rg-azmon-azd-e2e'; \ + location='swedencentral'; \ + targetRGs='rg-groceryapp,rg-contoso-swe'; \ + lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/Microsoft.OperationalInsights/workspaces/law-7defkiyvn3r44'; \ + appInsightsId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/microsoft.insights/components/sreagent-recipes-telemetry'; \ + appInsightsAppId='3b50188a-a191-4f74-994a-2e7ed8afc018' \ + } \ + -Output '/tmp/azmon-azd-e2e/'" + +# azd deploy +mkdir -p "./agents/azmon-azd-e2e" +cp -r /tmp/azmon-azd-e2e/* ./agents/azmon-azd-e2e/ 2>/dev/null || true +azd env select azmon-azd-e2e --no-prompt 2>/dev/null || azd env new azmon-azd-e2e --no-prompt +azd env set AZURE_AGENT_NAME azmon-azd-e2e --no-prompt +azd env set AZURE_RESOURCE_GROUP rg-azmon-azd-e2e --no-prompt +azd env set AZURE_LOCATION swedencentral --no-prompt +azd env set AZURE_SUBSCRIPTION_ID cbf44432-7f45-4906-a85d-d2b14a1e8328 --no-prompt +azd up --no-prompt + +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-azmon-azd-e2e' -AgentName 'azmon-azd-e2e'" + +# chat — save tastes +ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-azmon-azd-e2e -n azmon-azd-e2e --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS -X POST "$ENDPOINT/api/v1/threads" \ + -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' + +# wait for tastes.md +for i in $(seq 1 12); do + sleep 10 + TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) + if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then + break + fi +done + +# clone +pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'azmon-azd-e2e' -FromResourceGroup 'rg-azmon-azd-e2e' -AgentName 'azmon-azd-e2e-cl' -ResourceGroup 'rg-azmon-azd-e2e-cl' -Force" + +# verify clone + synth knowledge +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-azmon-azd-e2e-cl' -AgentName 'azmon-azd-e2e-cl'" +CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-azmon-azd-e2e-cl -n azmon-azd-e2e-cl --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-azmon-bicep-ps.sh b/sreagent-templates/tests/e2e-ps/test-azmon-bicep-ps.sh new file mode 100755 index 000000000..ba3d45db8 --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/test-azmon-bicep-ps.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# E2E: azmon-lawappinsights × bicep +set -uo pipefail +cd "$(dirname "$0")/../.." + +pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ + -Recipe 'azmon-lawappinsights' \ + -NonInteractive \ + -Set @{ \ + agentName='azmon-bic-e2e'; \ + resourceGroup='rg-azmon-bic-e2e'; \ + location='swedencentral'; \ + targetRGs='rg-contoso-swe,rg-ebc-demo3'; \ + lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/Microsoft.OperationalInsights/workspaces/law-7defkiyvn3r44'; \ + appInsightsId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/microsoft.insights/components/sreagent-recipes-telemetry'; \ + appInsightsAppId='3b50188a-a191-4f74-994a-2e7ed8afc018' \ + } \ + -Output '/tmp/azmon-bic-e2e/'" + +pwsh -NoProfile -Command "& './bin/ps/Deploy-Agent.ps1' -InputPath '/tmp/azmon-bic-e2e' -Force" + +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-azmon-bic-e2e' -AgentName 'azmon-bic-e2e'" + +# chat — save tastes +ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-azmon-bic-e2e -n azmon-bic-e2e --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS -X POST "$ENDPOINT/api/v1/threads" \ + -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' + +# wait for tastes.md +for i in $(seq 1 12); do + sleep 10 + TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) + if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then + break + fi +done + +# clone +pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'azmon-bic-e2e' -FromResourceGroup 'rg-azmon-bic-e2e' -AgentName 'azmon-bic-e2e-cl' -ResourceGroup 'rg-azmon-bic-e2e-cl' -Force" + +# verify clone + synth knowledge +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-azmon-bic-e2e-cl' -AgentName 'azmon-bic-e2e-cl'" +CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-azmon-bic-e2e-cl -n azmon-bic-e2e-cl --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-azmon-tf-ps.sh b/sreagent-templates/tests/e2e-ps/test-azmon-tf-ps.sh new file mode 100755 index 000000000..f9f44abf8 --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/test-azmon-tf-ps.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# E2E: azmon-lawappinsights × terraform +set -uo pipefail +cd "$(dirname "$0")/../.." + +pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ + -Recipe 'azmon-lawappinsights' \ + -NonInteractive \ + -Set @{ \ + agentName='azmon-tf-e2e'; \ + resourceGroup='rg-azmon-tf-e2e'; \ + location='swedencentral'; \ + targetRGs='aks-demo-app-cluster'; \ + lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/Microsoft.OperationalInsights/workspaces/law-7defkiyvn3r44'; \ + appInsightsId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/microsoft.insights/components/sreagent-recipes-telemetry'; \ + appInsightsAppId='3b50188a-a191-4f74-994a-2e7ed8afc018' \ + } \ + -Output '/tmp/azmon-tf-e2e/'" + +pwsh -NoProfile -Command "& './bin/ps/Deploy-Tf.ps1' -InputPath '/tmp/azmon-tf-e2e'" + +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-azmon-tf-e2e' -AgentName 'azmon-tf-e2e'" + +# chat — save tastes +ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-azmon-tf-e2e -n azmon-tf-e2e --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS -X POST "$ENDPOINT/api/v1/threads" \ + -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' + +# wait for tastes.md +for i in $(seq 1 12); do + sleep 10 + TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) + if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then + break + fi +done + +# clone +pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'azmon-tf-e2e' -FromResourceGroup 'rg-azmon-tf-e2e' -AgentName 'azmon-tf-e2e-cl' -ResourceGroup 'rg-azmon-tf-e2e-cl' -Backend 'terraform' -Force" + +# verify clone + synth knowledge +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-azmon-tf-e2e-cl' -AgentName 'azmon-tf-e2e-cl'" +CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-azmon-tf-e2e-cl -n azmon-tf-e2e-cl --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-dt-azd-ps.sh b/sreagent-templates/tests/e2e-ps/test-dt-azd-ps.sh new file mode 100755 index 000000000..f293fcc53 --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/test-dt-azd-ps.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# E2E: dynatrace-mcp × azd +set -uo pipefail +: "${DT_TOKEN:?Set DT_TOKEN env var}" +cd "$(dirname "$0")/../.." + +pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ + -Recipe 'dynatrace-mcp' \ + -NonInteractive \ + -Set @{ \ + agentName='dt-azd-e2e'; \ + resourceGroup='rg-dt-azd-e2e'; \ + location='swedencentral'; \ + targetRGs='rg-contoso-eus2'; \ + lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/Microsoft.OperationalInsights/workspaces/law-7defkiyvn3r44'; \ + dtTenant='dhu66396'; \ + dtToken='$DT_TOKEN' \ + } \ + -Output '/tmp/dt-azd-e2e/'" + +# azd deploy +mkdir -p "./agents/dt-azd-e2e" +cp -r /tmp/dt-azd-e2e/* ./agents/dt-azd-e2e/ 2>/dev/null || true +azd env select dt-azd-e2e --no-prompt 2>/dev/null || azd env new dt-azd-e2e --no-prompt +azd env set AZURE_AGENT_NAME dt-azd-e2e --no-prompt +azd env set AZURE_RESOURCE_GROUP rg-dt-azd-e2e --no-prompt +azd env set AZURE_LOCATION swedencentral --no-prompt +azd env set AZURE_SUBSCRIPTION_ID cbf44432-7f45-4906-a85d-d2b14a1e8328 --no-prompt +azd up --no-prompt + +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-dt-azd-e2e' -AgentName 'dt-azd-e2e'" + +# chat — save tastes +ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-dt-azd-e2e -n dt-azd-e2e --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS -X POST "$ENDPOINT/api/v1/threads" \ + -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' + +# wait for tastes.md +for i in $(seq 1 12); do + sleep 10 + TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) + if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then + break + fi +done + +# clone +pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'dt-azd-e2e' -FromResourceGroup 'rg-dt-azd-e2e' -AgentName 'dt-azd-e2e-cl' -ResourceGroup 'rg-dt-azd-e2e-cl' -Force" + +# verify clone + synth knowledge +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-dt-azd-e2e-cl' -AgentName 'dt-azd-e2e-cl'" +CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-dt-azd-e2e-cl -n dt-azd-e2e-cl --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-dt-bicep-ps.sh b/sreagent-templates/tests/e2e-ps/test-dt-bicep-ps.sh new file mode 100755 index 000000000..43c9dd890 --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/test-dt-bicep-ps.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# E2E: dynatrace-mcp × bicep +set -uo pipefail +: "${DT_TOKEN:?Set DT_TOKEN env var}" +cd "$(dirname "$0")/../.." + +pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ + -Recipe 'dynatrace-mcp' \ + -NonInteractive \ + -Set @{ \ + agentName='dt-bic-e2e'; \ + resourceGroup='rg-dt-bic-e2e'; \ + location='swedencentral'; \ + targetRGs='rg-contoso-swe,rg-aks-journal'; \ + lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/Microsoft.OperationalInsights/workspaces/law-7defkiyvn3r44'; \ + dtTenant='dhu66396'; \ + dtToken='$DT_TOKEN' \ + } \ + -Output '/tmp/dt-bic-e2e/'" + +pwsh -NoProfile -Command "& './bin/ps/Deploy-Agent.ps1' -InputPath '/tmp/dt-bic-e2e' -Force" + +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-dt-bic-e2e' -AgentName 'dt-bic-e2e'" + +# chat — save tastes +ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-dt-bic-e2e -n dt-bic-e2e --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS -X POST "$ENDPOINT/api/v1/threads" \ + -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' + +# wait for tastes.md +for i in $(seq 1 12); do + sleep 10 + TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) + if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then + break + fi +done + +# clone +pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'dt-bic-e2e' -FromResourceGroup 'rg-dt-bic-e2e' -AgentName 'dt-bic-e2e-cl' -ResourceGroup 'rg-dt-bic-e2e-cl' -Force" + +# verify clone + synth knowledge +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-dt-bic-e2e-cl' -AgentName 'dt-bic-e2e-cl'" +CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-dt-bic-e2e-cl -n dt-bic-e2e-cl --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-dt-tf-ps.sh b/sreagent-templates/tests/e2e-ps/test-dt-tf-ps.sh new file mode 100755 index 000000000..af2dbf848 --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/test-dt-tf-ps.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# E2E: dynatrace-mcp × terraform +set -uo pipefail +: "${DT_TOKEN:?Set DT_TOKEN env var}" +cd "$(dirname "$0")/../.." + +pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ + -Recipe 'dynatrace-mcp' \ + -NonInteractive \ + -Set @{ \ + agentName='dt-tf-e2e'; \ + resourceGroup='rg-dt-tf-e2e'; \ + location='swedencentral'; \ + targetRGs='rg-ebc-demo3,aks-demo-app-cluster'; \ + lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-ebc-demo3/providers/Microsoft.OperationalInsights/workspaces/law-ebc-demo3'; \ + dtTenant='dhu66396'; \ + dtToken='$DT_TOKEN' \ + } \ + -Output '/tmp/dt-tf-e2e/'" + +pwsh -NoProfile -Command "& './bin/ps/Deploy-Tf.ps1' -InputPath '/tmp/dt-tf-e2e'" + +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-dt-tf-e2e' -AgentName 'dt-tf-e2e'" + +# chat — save tastes +ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-dt-tf-e2e -n dt-tf-e2e --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS -X POST "$ENDPOINT/api/v1/threads" \ + -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' + +# wait for tastes.md +for i in $(seq 1 12); do + sleep 10 + TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) + if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then + break + fi +done + +# clone +pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'dt-tf-e2e' -FromResourceGroup 'rg-dt-tf-e2e' -AgentName 'dt-tf-e2e-cl' -ResourceGroup 'rg-dt-tf-e2e-cl' -Backend 'terraform' -Force" + +# verify clone + synth knowledge +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-dt-tf-e2e-cl' -AgentName 'dt-tf-e2e-cl'" +CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-dt-tf-e2e-cl -n dt-tf-e2e-cl --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-min-azd-ps.sh b/sreagent-templates/tests/e2e-ps/test-min-azd-ps.sh new file mode 100755 index 000000000..d81332c7e --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/test-min-azd-ps.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# E2E: minimal × azd +set -uo pipefail +cd "$(dirname "$0")/../.." + +pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ + -Recipe 'minimal' \ + -NonInteractive \ + -Set @{ \ + agentName='min-azd-e2e'; \ + resourceGroup='rg-min-azd-e2e'; \ + location='swedencentral'; \ + targetRGs='aks-demo-app-cluster,rg-aks-journal' \ + } \ + -Output '/tmp/min-azd-e2e/'" + +# azd deploy +mkdir -p "./agents/min-azd-e2e" +cp -r /tmp/min-azd-e2e/* ./agents/min-azd-e2e/ 2>/dev/null || true +azd env select min-azd-e2e --no-prompt 2>/dev/null || azd env new min-azd-e2e --no-prompt +azd env set AZURE_AGENT_NAME min-azd-e2e --no-prompt +azd env set AZURE_RESOURCE_GROUP rg-min-azd-e2e --no-prompt +azd env set AZURE_LOCATION swedencentral --no-prompt +azd env set AZURE_SUBSCRIPTION_ID cbf44432-7f45-4906-a85d-d2b14a1e8328 --no-prompt +azd up --no-prompt + +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-min-azd-e2e' -AgentName 'min-azd-e2e'" + +# chat — save tastes +ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-min-azd-e2e -n min-azd-e2e --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS -X POST "$ENDPOINT/api/v1/threads" \ + -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' + +# wait for tastes.md +for i in $(seq 1 12); do + sleep 10 + TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) + if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then + break + fi +done + +# clone +pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'min-azd-e2e' -FromResourceGroup 'rg-min-azd-e2e' -AgentName 'min-azd-e2e-cl' -ResourceGroup 'rg-min-azd-e2e-cl' -Force" + +# verify clone + synth knowledge +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-min-azd-e2e-cl' -AgentName 'min-azd-e2e-cl'" +CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-min-azd-e2e-cl -n min-azd-e2e-cl --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-min-bicep-ps.sh b/sreagent-templates/tests/e2e-ps/test-min-bicep-ps.sh new file mode 100755 index 000000000..20eb36799 --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/test-min-bicep-ps.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# E2E: minimal × bicep +set -uo pipefail +cd "$(dirname "$0")/../.." + +pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ + -Recipe 'minimal' \ + -NonInteractive \ + -Set @{ \ + agentName='min-bic-e2e'; \ + resourceGroup='rg-min-bic-e2e'; \ + location='swedencentral'; \ + targetRGs='rg-ebc-demo3' \ + } \ + -Output '/tmp/min-bic-e2e/'" + +pwsh -NoProfile -Command "& './bin/ps/Deploy-Agent.ps1' -InputPath '/tmp/min-bic-e2e' -Force" + +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-min-bic-e2e' -AgentName 'min-bic-e2e'" + +# chat — save tastes +ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-min-bic-e2e -n min-bic-e2e --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS -X POST "$ENDPOINT/api/v1/threads" \ + -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' + +# wait for tastes.md +for i in $(seq 1 12); do + sleep 10 + TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) + if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then + break + fi +done + +# clone +pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'min-bic-e2e' -FromResourceGroup 'rg-min-bic-e2e' -AgentName 'min-bic-e2e-cl' -ResourceGroup 'rg-min-bic-e2e-cl' -Force" + +# verify clone + synth knowledge +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-min-bic-e2e-cl' -AgentName 'min-bic-e2e-cl'" +CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-min-bic-e2e-cl -n min-bic-e2e-cl --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-min-tf-ps.sh b/sreagent-templates/tests/e2e-ps/test-min-tf-ps.sh new file mode 100755 index 000000000..7b1aefd1b --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/test-min-tf-ps.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# E2E: minimal × terraform +set -uo pipefail +cd "$(dirname "$0")/../.." + +pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ + -Recipe 'minimal' \ + -NonInteractive \ + -Set @{ \ + agentName='min-tf-e2e'; \ + resourceGroup='rg-min-tf-e2e'; \ + location='swedencentral'; \ + targetRGs='rg-contoso-swe,rg-groceryapp' \ + } \ + -Output '/tmp/min-tf-e2e/'" + +pwsh -NoProfile -Command "& './bin/ps/Deploy-Tf.ps1' -InputPath '/tmp/min-tf-e2e'" + +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-min-tf-e2e' -AgentName 'min-tf-e2e'" + +# chat — save tastes +ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-min-tf-e2e -n min-tf-e2e --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS -X POST "$ENDPOINT/api/v1/threads" \ + -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' + +# wait for tastes.md +for i in $(seq 1 12); do + sleep 10 + TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) + if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then + break + fi +done + +# clone +pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'min-tf-e2e' -FromResourceGroup 'rg-min-tf-e2e' -AgentName 'min-tf-e2e-cl' -ResourceGroup 'rg-min-tf-e2e-cl' -Backend 'terraform' -Force" + +# verify clone + synth knowledge +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-min-tf-e2e-cl' -AgentName 'min-tf-e2e-cl'" +CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-min-tf-e2e-cl -n min-tf-e2e-cl --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-pd-azd-ps.sh b/sreagent-templates/tests/e2e-ps/test-pd-azd-ps.sh new file mode 100755 index 000000000..6e43c636f --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/test-pd-azd-ps.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +# E2E: pagerduty-law-vmcosmos × azd +set -uo pipefail +cd "$(dirname "$0")/../.." + +pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ + -Recipe 'pagerduty-law-vmcosmos' \ + -NonInteractive \ + -Set @{ \ + agentName='pd-azd-e2e'; \ + resourceGroup='rg-pd-azd-e2e'; \ + location='swedencentral'; \ + targetRGs='rg-groceryapp'; \ + lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-ebc-demo3/providers/Microsoft.OperationalInsights/workspaces/law-ebc-demo3'; \ + pagerdutyApiKey='u+fake-pd-key' \ + } \ + -Output '/tmp/pd-azd-e2e/'" + +# azd deploy +mkdir -p "./agents/pd-azd-e2e" +cp -r /tmp/pd-azd-e2e/* ./agents/pd-azd-e2e/ 2>/dev/null || true +azd env select pd-azd-e2e --no-prompt 2>/dev/null || azd env new pd-azd-e2e --no-prompt +azd env set AZURE_AGENT_NAME pd-azd-e2e --no-prompt +azd env set AZURE_RESOURCE_GROUP rg-pd-azd-e2e --no-prompt +azd env set AZURE_LOCATION swedencentral --no-prompt +azd env set AZURE_SUBSCRIPTION_ID cbf44432-7f45-4906-a85d-d2b14a1e8328 --no-prompt +azd up --no-prompt + +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-pd-azd-e2e' -AgentName 'pd-azd-e2e'" + +# chat — save tastes +ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-pd-azd-e2e -n pd-azd-e2e --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS -X POST "$ENDPOINT/api/v1/threads" \ + -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' + +# wait for tastes.md +for i in $(seq 1 12); do + sleep 10 + TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) + if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then + break + fi +done + +# clone +pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'pd-azd-e2e' -FromResourceGroup 'rg-pd-azd-e2e' -AgentName 'pd-azd-e2e-cl' -ResourceGroup 'rg-pd-azd-e2e-cl' -Force" + +# verify clone + synth knowledge +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-pd-azd-e2e-cl' -AgentName 'pd-azd-e2e-cl'" +CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-pd-azd-e2e-cl -n pd-azd-e2e-cl --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-pd-bicep-ps.sh b/sreagent-templates/tests/e2e-ps/test-pd-bicep-ps.sh new file mode 100755 index 000000000..18c1a1325 --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/test-pd-bicep-ps.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# E2E: pagerduty-law-vmcosmos × bicep +set -uo pipefail +cd "$(dirname "$0")/../.." + +pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ + -Recipe 'pagerduty-law-vmcosmos' \ + -NonInteractive \ + -Set @{ \ + agentName='pd-bic-e2e'; \ + resourceGroup='rg-pd-bic-e2e'; \ + location='swedencentral'; \ + targetRGs='rg-ebc-demo3,rg-contoso-eus2'; \ + lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-ebc-demo3/providers/Microsoft.OperationalInsights/workspaces/law-ebc-demo3'; \ + pagerdutyApiKey='u+fake-pd-key' \ + } \ + -Output '/tmp/pd-bic-e2e/'" + +pwsh -NoProfile -Command "& './bin/ps/Deploy-Agent.ps1' -InputPath '/tmp/pd-bic-e2e' -Force" + +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-pd-bic-e2e' -AgentName 'pd-bic-e2e'" + +# chat — save tastes +ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-pd-bic-e2e -n pd-bic-e2e --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS -X POST "$ENDPOINT/api/v1/threads" \ + -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' + +# wait for tastes.md +for i in $(seq 1 12); do + sleep 10 + TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) + if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then + break + fi +done + +# clone +pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'pd-bic-e2e' -FromResourceGroup 'rg-pd-bic-e2e' -AgentName 'pd-bic-e2e-cl' -ResourceGroup 'rg-pd-bic-e2e-cl' -Force" + +# verify clone + synth knowledge +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-pd-bic-e2e-cl' -AgentName 'pd-bic-e2e-cl'" +CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-pd-bic-e2e-cl -n pd-bic-e2e-cl --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-pd-tf-ps.sh b/sreagent-templates/tests/e2e-ps/test-pd-tf-ps.sh new file mode 100755 index 000000000..eb0af11ef --- /dev/null +++ b/sreagent-templates/tests/e2e-ps/test-pd-tf-ps.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# E2E: pagerduty-law-vmcosmos × terraform +set -uo pipefail +cd "$(dirname "$0")/../.." + +pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ + -Recipe 'pagerduty-law-vmcosmos' \ + -NonInteractive \ + -Set @{ \ + agentName='pd-tf-e2e'; \ + resourceGroup='rg-pd-tf-e2e'; \ + location='swedencentral'; \ + targetRGs='aks-demo-app-cluster,rg-contoso-swe'; \ + lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/Microsoft.OperationalInsights/workspaces/law-7defkiyvn3r44'; \ + pagerdutyApiKey='u+fake-pd-key' \ + } \ + -Output '/tmp/pd-tf-e2e/'" + +pwsh -NoProfile -Command "& './bin/ps/Deploy-Tf.ps1' -InputPath '/tmp/pd-tf-e2e'" + +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-pd-tf-e2e' -AgentName 'pd-tf-e2e'" + +# chat — save tastes +ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-pd-tf-e2e -n pd-tf-e2e --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS -X POST "$ENDPOINT/api/v1/threads" \ + -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ + -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' + +# wait for tastes.md +for i in $(seq 1 12); do + sleep 10 + TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) + if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then + break + fi +done + +# clone +pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'pd-tf-e2e' -FromResourceGroup 'rg-pd-tf-e2e' -AgentName 'pd-tf-e2e-cl' -ResourceGroup 'rg-pd-tf-e2e-cl' -Backend 'terraform' -Force" + +# verify clone + synth knowledge +pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-pd-tf-e2e-cl' -AgentName 'pd-tf-e2e-cl'" +CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-pd-tf-e2e-cl -n pd-tf-e2e-cl --query "properties.agentEndpoint" -o tsv) +TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) +curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ + -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true From 644334d742c9a475679830086677c505937d7a39 Mon Sep 17 00:00:00 2001 From: dm-chelupati Date: Mon, 18 May 2026 17:13:14 -0700 Subject: [PATCH 18/18] chore: remove e2e test scripts with personal values --- .../tests/e2e-ps/run-all-ps-e2e.sh | 107 ------------------ .../tests/e2e-ps/test-azmon-azd-ps.sh | 57 ---------- .../tests/e2e-ps/test-azmon-bicep-ps.sh | 49 -------- .../tests/e2e-ps/test-azmon-tf-ps.sh | 49 -------- .../tests/e2e-ps/test-dt-azd-ps.sh | 58 ---------- .../tests/e2e-ps/test-dt-bicep-ps.sh | 50 -------- .../tests/e2e-ps/test-dt-tf-ps.sh | 50 -------- .../tests/e2e-ps/test-min-azd-ps.sh | 54 --------- .../tests/e2e-ps/test-min-bicep-ps.sh | 46 -------- .../tests/e2e-ps/test-min-tf-ps.sh | 46 -------- .../tests/e2e-ps/test-pd-azd-ps.sh | 56 --------- .../tests/e2e-ps/test-pd-bicep-ps.sh | 48 -------- .../tests/e2e-ps/test-pd-tf-ps.sh | 48 -------- 13 files changed, 718 deletions(-) delete mode 100755 sreagent-templates/tests/e2e-ps/run-all-ps-e2e.sh delete mode 100755 sreagent-templates/tests/e2e-ps/test-azmon-azd-ps.sh delete mode 100755 sreagent-templates/tests/e2e-ps/test-azmon-bicep-ps.sh delete mode 100755 sreagent-templates/tests/e2e-ps/test-azmon-tf-ps.sh delete mode 100755 sreagent-templates/tests/e2e-ps/test-dt-azd-ps.sh delete mode 100755 sreagent-templates/tests/e2e-ps/test-dt-bicep-ps.sh delete mode 100755 sreagent-templates/tests/e2e-ps/test-dt-tf-ps.sh delete mode 100755 sreagent-templates/tests/e2e-ps/test-min-azd-ps.sh delete mode 100755 sreagent-templates/tests/e2e-ps/test-min-bicep-ps.sh delete mode 100755 sreagent-templates/tests/e2e-ps/test-min-tf-ps.sh delete mode 100755 sreagent-templates/tests/e2e-ps/test-pd-azd-ps.sh delete mode 100755 sreagent-templates/tests/e2e-ps/test-pd-bicep-ps.sh delete mode 100755 sreagent-templates/tests/e2e-ps/test-pd-tf-ps.sh diff --git a/sreagent-templates/tests/e2e-ps/run-all-ps-e2e.sh b/sreagent-templates/tests/e2e-ps/run-all-ps-e2e.sh deleted file mode 100755 index 91bb78b11..000000000 --- a/sreagent-templates/tests/e2e-ps/run-all-ps-e2e.sh +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env bash -# run-all-ps-e2e.sh — Run all 12 PS e2e tests (4 recipes × 3 backends) -# Run from sreagent-templates/ directory -# Usage: -# ./tests/e2e-ps/run-all-ps-e2e.sh # run all 12 tests -# ./tests/e2e-ps/run-all-ps-e2e.sh azmon # run only azmon tests -# ./tests/e2e-ps/run-all-ps-e2e.sh dt bicep # run dt-bicep only -# -# Requires: DT_TOKEN env var (for dynatrace tests) -set -uo pipefail - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -REPORT="/tmp/e2e-ps-matrix-results.txt" -> "$REPORT" - -TOTAL_PASS=0; TOTAL_FAIL=0; TOTAL_SKIP=0 -RESULTS=() - -FILTER_RECIPE="${1:-}" -FILTER_BACKEND="${2:-}" - -TESTS=( - "test-azmon-bicep-ps.sh" - "test-azmon-tf-ps.sh" - "test-azmon-azd-ps.sh" - "test-pd-bicep-ps.sh" - "test-pd-tf-ps.sh" - "test-pd-azd-ps.sh" - "test-dt-bicep-ps.sh" - "test-dt-tf-ps.sh" - "test-dt-azd-ps.sh" - "test-min-bicep-ps.sh" - "test-min-tf-ps.sh" - "test-min-azd-ps.sh" -) - -log() { echo "$1" | tee -a "$REPORT"; } - -log "╔══════════════════════════════════════════════════════╗" -log "║ E2E PS Matrix — 4 recipes × 3 backends ║" -log "║ Started: $(date) ║" -log "╚══════════════════════════════════════════════════════╝" -log "" - -# Pre-flight: check DT_TOKEN for dt tests -if [[ -z "${DT_TOKEN:-}" ]]; then - log "⚠️ DT_TOKEN not set — dynatrace tests will be skipped" -fi - -for test in "${TESTS[@]}"; do - # Extract recipe and backend from filename: test-{recipe}-{backend}-ps.sh - recipe=$(echo "$test" | sed 's/test-//' | sed 's/-ps\.sh//' | rev | cut -d- -f2- | rev) - backend=$(echo "$test" | sed 's/test-//' | sed 's/-ps\.sh//' | rev | cut -d- -f1 | rev) - - # Apply filters - if [[ -n "$FILTER_RECIPE" && "$recipe" != *"$FILTER_RECIPE"* ]]; then - continue - fi - if [[ -n "$FILTER_BACKEND" && "$backend" != *"$FILTER_BACKEND"* ]]; then - continue - fi - - # Skip dt tests if no DT_TOKEN - if [[ "$recipe" == *"dt"* && -z "${DT_TOKEN:-}" ]]; then - log "⏭️ SKIP: $test (DT_TOKEN not set)" - RESULTS+=("SKIP: $test") - ((TOTAL_SKIP++)) - continue - fi - - log "────────────────────────────────────────" - log "▶ Running: $test" - log "────────────────────────────────────────" - - START_TIME=$(date +%s) - bash "$SCRIPT_DIR/$test" - RC=$? - END_TIME=$(date +%s) - DURATION=$((END_TIME - START_TIME)) - - if [[ $RC -eq 0 ]]; then - log "✅ PASS: $test (${DURATION}s)" - RESULTS+=("PASS: $test (${DURATION}s)") - ((TOTAL_PASS++)) - else - log "❌ FAIL: $test (rc=$RC, ${DURATION}s)" - RESULTS+=("FAIL: $test (rc=$RC, ${DURATION}s)") - ((TOTAL_FAIL++)) - fi - log "" -done - -log "" -log "╔══════════════════════════════════════════════════════╗" -log "║ FINAL RESULTS ║" -log "╠══════════════════════════════════════════════════════╣" -for r in "${RESULTS[@]}"; do - log "║ $r" -done -log "╠══════════════════════════════════════════════════════╣" -log "║ PASS: $TOTAL_PASS FAIL: $TOTAL_FAIL SKIP: $TOTAL_SKIP" -log "║ Finished: $(date)" -log "╚══════════════════════════════════════════════════════╝" -log "" -log "Full report: $REPORT" - -[[ $TOTAL_FAIL -eq 0 ]] && exit 0 || exit 1 diff --git a/sreagent-templates/tests/e2e-ps/test-azmon-azd-ps.sh b/sreagent-templates/tests/e2e-ps/test-azmon-azd-ps.sh deleted file mode 100755 index 58725cb45..000000000 --- a/sreagent-templates/tests/e2e-ps/test-azmon-azd-ps.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bash -# E2E: azmon-lawappinsights × azd -set -uo pipefail -cd "$(dirname "$0")/../.." - -pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ - -Recipe 'azmon-lawappinsights' \ - -NonInteractive \ - -Set @{ \ - agentName='azmon-azd-e2e'; \ - resourceGroup='rg-azmon-azd-e2e'; \ - location='swedencentral'; \ - targetRGs='rg-groceryapp,rg-contoso-swe'; \ - lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/Microsoft.OperationalInsights/workspaces/law-7defkiyvn3r44'; \ - appInsightsId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/microsoft.insights/components/sreagent-recipes-telemetry'; \ - appInsightsAppId='3b50188a-a191-4f74-994a-2e7ed8afc018' \ - } \ - -Output '/tmp/azmon-azd-e2e/'" - -# azd deploy -mkdir -p "./agents/azmon-azd-e2e" -cp -r /tmp/azmon-azd-e2e/* ./agents/azmon-azd-e2e/ 2>/dev/null || true -azd env select azmon-azd-e2e --no-prompt 2>/dev/null || azd env new azmon-azd-e2e --no-prompt -azd env set AZURE_AGENT_NAME azmon-azd-e2e --no-prompt -azd env set AZURE_RESOURCE_GROUP rg-azmon-azd-e2e --no-prompt -azd env set AZURE_LOCATION swedencentral --no-prompt -azd env set AZURE_SUBSCRIPTION_ID cbf44432-7f45-4906-a85d-d2b14a1e8328 --no-prompt -azd up --no-prompt - -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-azmon-azd-e2e' -AgentName 'azmon-azd-e2e'" - -# chat — save tastes -ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-azmon-azd-e2e -n azmon-azd-e2e --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS -X POST "$ENDPOINT/api/v1/threads" \ - -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' - -# wait for tastes.md -for i in $(seq 1 12); do - sleep 10 - TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) - if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then - break - fi -done - -# clone -pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'azmon-azd-e2e' -FromResourceGroup 'rg-azmon-azd-e2e' -AgentName 'azmon-azd-e2e-cl' -ResourceGroup 'rg-azmon-azd-e2e-cl' -Force" - -# verify clone + synth knowledge -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-azmon-azd-e2e-cl' -AgentName 'azmon-azd-e2e-cl'" -CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-azmon-azd-e2e-cl -n azmon-azd-e2e-cl --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-azmon-bicep-ps.sh b/sreagent-templates/tests/e2e-ps/test-azmon-bicep-ps.sh deleted file mode 100755 index ba3d45db8..000000000 --- a/sreagent-templates/tests/e2e-ps/test-azmon-bicep-ps.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env bash -# E2E: azmon-lawappinsights × bicep -set -uo pipefail -cd "$(dirname "$0")/../.." - -pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ - -Recipe 'azmon-lawappinsights' \ - -NonInteractive \ - -Set @{ \ - agentName='azmon-bic-e2e'; \ - resourceGroup='rg-azmon-bic-e2e'; \ - location='swedencentral'; \ - targetRGs='rg-contoso-swe,rg-ebc-demo3'; \ - lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/Microsoft.OperationalInsights/workspaces/law-7defkiyvn3r44'; \ - appInsightsId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/microsoft.insights/components/sreagent-recipes-telemetry'; \ - appInsightsAppId='3b50188a-a191-4f74-994a-2e7ed8afc018' \ - } \ - -Output '/tmp/azmon-bic-e2e/'" - -pwsh -NoProfile -Command "& './bin/ps/Deploy-Agent.ps1' -InputPath '/tmp/azmon-bic-e2e' -Force" - -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-azmon-bic-e2e' -AgentName 'azmon-bic-e2e'" - -# chat — save tastes -ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-azmon-bic-e2e -n azmon-bic-e2e --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS -X POST "$ENDPOINT/api/v1/threads" \ - -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' - -# wait for tastes.md -for i in $(seq 1 12); do - sleep 10 - TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) - if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then - break - fi -done - -# clone -pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'azmon-bic-e2e' -FromResourceGroup 'rg-azmon-bic-e2e' -AgentName 'azmon-bic-e2e-cl' -ResourceGroup 'rg-azmon-bic-e2e-cl' -Force" - -# verify clone + synth knowledge -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-azmon-bic-e2e-cl' -AgentName 'azmon-bic-e2e-cl'" -CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-azmon-bic-e2e-cl -n azmon-bic-e2e-cl --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-azmon-tf-ps.sh b/sreagent-templates/tests/e2e-ps/test-azmon-tf-ps.sh deleted file mode 100755 index f9f44abf8..000000000 --- a/sreagent-templates/tests/e2e-ps/test-azmon-tf-ps.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env bash -# E2E: azmon-lawappinsights × terraform -set -uo pipefail -cd "$(dirname "$0")/../.." - -pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ - -Recipe 'azmon-lawappinsights' \ - -NonInteractive \ - -Set @{ \ - agentName='azmon-tf-e2e'; \ - resourceGroup='rg-azmon-tf-e2e'; \ - location='swedencentral'; \ - targetRGs='aks-demo-app-cluster'; \ - lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/Microsoft.OperationalInsights/workspaces/law-7defkiyvn3r44'; \ - appInsightsId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/microsoft.insights/components/sreagent-recipes-telemetry'; \ - appInsightsAppId='3b50188a-a191-4f74-994a-2e7ed8afc018' \ - } \ - -Output '/tmp/azmon-tf-e2e/'" - -pwsh -NoProfile -Command "& './bin/ps/Deploy-Tf.ps1' -InputPath '/tmp/azmon-tf-e2e'" - -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-azmon-tf-e2e' -AgentName 'azmon-tf-e2e'" - -# chat — save tastes -ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-azmon-tf-e2e -n azmon-tf-e2e --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS -X POST "$ENDPOINT/api/v1/threads" \ - -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' - -# wait for tastes.md -for i in $(seq 1 12); do - sleep 10 - TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) - if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then - break - fi -done - -# clone -pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'azmon-tf-e2e' -FromResourceGroup 'rg-azmon-tf-e2e' -AgentName 'azmon-tf-e2e-cl' -ResourceGroup 'rg-azmon-tf-e2e-cl' -Backend 'terraform' -Force" - -# verify clone + synth knowledge -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-azmon-tf-e2e-cl' -AgentName 'azmon-tf-e2e-cl'" -CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-azmon-tf-e2e-cl -n azmon-tf-e2e-cl --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-dt-azd-ps.sh b/sreagent-templates/tests/e2e-ps/test-dt-azd-ps.sh deleted file mode 100755 index f293fcc53..000000000 --- a/sreagent-templates/tests/e2e-ps/test-dt-azd-ps.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env bash -# E2E: dynatrace-mcp × azd -set -uo pipefail -: "${DT_TOKEN:?Set DT_TOKEN env var}" -cd "$(dirname "$0")/../.." - -pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ - -Recipe 'dynatrace-mcp' \ - -NonInteractive \ - -Set @{ \ - agentName='dt-azd-e2e'; \ - resourceGroup='rg-dt-azd-e2e'; \ - location='swedencentral'; \ - targetRGs='rg-contoso-eus2'; \ - lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/Microsoft.OperationalInsights/workspaces/law-7defkiyvn3r44'; \ - dtTenant='dhu66396'; \ - dtToken='$DT_TOKEN' \ - } \ - -Output '/tmp/dt-azd-e2e/'" - -# azd deploy -mkdir -p "./agents/dt-azd-e2e" -cp -r /tmp/dt-azd-e2e/* ./agents/dt-azd-e2e/ 2>/dev/null || true -azd env select dt-azd-e2e --no-prompt 2>/dev/null || azd env new dt-azd-e2e --no-prompt -azd env set AZURE_AGENT_NAME dt-azd-e2e --no-prompt -azd env set AZURE_RESOURCE_GROUP rg-dt-azd-e2e --no-prompt -azd env set AZURE_LOCATION swedencentral --no-prompt -azd env set AZURE_SUBSCRIPTION_ID cbf44432-7f45-4906-a85d-d2b14a1e8328 --no-prompt -azd up --no-prompt - -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-dt-azd-e2e' -AgentName 'dt-azd-e2e'" - -# chat — save tastes -ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-dt-azd-e2e -n dt-azd-e2e --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS -X POST "$ENDPOINT/api/v1/threads" \ - -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' - -# wait for tastes.md -for i in $(seq 1 12); do - sleep 10 - TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) - if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then - break - fi -done - -# clone -pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'dt-azd-e2e' -FromResourceGroup 'rg-dt-azd-e2e' -AgentName 'dt-azd-e2e-cl' -ResourceGroup 'rg-dt-azd-e2e-cl' -Force" - -# verify clone + synth knowledge -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-dt-azd-e2e-cl' -AgentName 'dt-azd-e2e-cl'" -CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-dt-azd-e2e-cl -n dt-azd-e2e-cl --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-dt-bicep-ps.sh b/sreagent-templates/tests/e2e-ps/test-dt-bicep-ps.sh deleted file mode 100755 index 43c9dd890..000000000 --- a/sreagent-templates/tests/e2e-ps/test-dt-bicep-ps.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash -# E2E: dynatrace-mcp × bicep -set -uo pipefail -: "${DT_TOKEN:?Set DT_TOKEN env var}" -cd "$(dirname "$0")/../.." - -pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ - -Recipe 'dynatrace-mcp' \ - -NonInteractive \ - -Set @{ \ - agentName='dt-bic-e2e'; \ - resourceGroup='rg-dt-bic-e2e'; \ - location='swedencentral'; \ - targetRGs='rg-contoso-swe,rg-aks-journal'; \ - lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/Microsoft.OperationalInsights/workspaces/law-7defkiyvn3r44'; \ - dtTenant='dhu66396'; \ - dtToken='$DT_TOKEN' \ - } \ - -Output '/tmp/dt-bic-e2e/'" - -pwsh -NoProfile -Command "& './bin/ps/Deploy-Agent.ps1' -InputPath '/tmp/dt-bic-e2e' -Force" - -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-dt-bic-e2e' -AgentName 'dt-bic-e2e'" - -# chat — save tastes -ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-dt-bic-e2e -n dt-bic-e2e --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS -X POST "$ENDPOINT/api/v1/threads" \ - -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' - -# wait for tastes.md -for i in $(seq 1 12); do - sleep 10 - TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) - if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then - break - fi -done - -# clone -pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'dt-bic-e2e' -FromResourceGroup 'rg-dt-bic-e2e' -AgentName 'dt-bic-e2e-cl' -ResourceGroup 'rg-dt-bic-e2e-cl' -Force" - -# verify clone + synth knowledge -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-dt-bic-e2e-cl' -AgentName 'dt-bic-e2e-cl'" -CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-dt-bic-e2e-cl -n dt-bic-e2e-cl --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-dt-tf-ps.sh b/sreagent-templates/tests/e2e-ps/test-dt-tf-ps.sh deleted file mode 100755 index af2dbf848..000000000 --- a/sreagent-templates/tests/e2e-ps/test-dt-tf-ps.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash -# E2E: dynatrace-mcp × terraform -set -uo pipefail -: "${DT_TOKEN:?Set DT_TOKEN env var}" -cd "$(dirname "$0")/../.." - -pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ - -Recipe 'dynatrace-mcp' \ - -NonInteractive \ - -Set @{ \ - agentName='dt-tf-e2e'; \ - resourceGroup='rg-dt-tf-e2e'; \ - location='swedencentral'; \ - targetRGs='rg-ebc-demo3,aks-demo-app-cluster'; \ - lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-ebc-demo3/providers/Microsoft.OperationalInsights/workspaces/law-ebc-demo3'; \ - dtTenant='dhu66396'; \ - dtToken='$DT_TOKEN' \ - } \ - -Output '/tmp/dt-tf-e2e/'" - -pwsh -NoProfile -Command "& './bin/ps/Deploy-Tf.ps1' -InputPath '/tmp/dt-tf-e2e'" - -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-dt-tf-e2e' -AgentName 'dt-tf-e2e'" - -# chat — save tastes -ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-dt-tf-e2e -n dt-tf-e2e --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS -X POST "$ENDPOINT/api/v1/threads" \ - -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' - -# wait for tastes.md -for i in $(seq 1 12); do - sleep 10 - TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) - if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then - break - fi -done - -# clone -pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'dt-tf-e2e' -FromResourceGroup 'rg-dt-tf-e2e' -AgentName 'dt-tf-e2e-cl' -ResourceGroup 'rg-dt-tf-e2e-cl' -Backend 'terraform' -Force" - -# verify clone + synth knowledge -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-dt-tf-e2e-cl' -AgentName 'dt-tf-e2e-cl'" -CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-dt-tf-e2e-cl -n dt-tf-e2e-cl --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-min-azd-ps.sh b/sreagent-templates/tests/e2e-ps/test-min-azd-ps.sh deleted file mode 100755 index d81332c7e..000000000 --- a/sreagent-templates/tests/e2e-ps/test-min-azd-ps.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env bash -# E2E: minimal × azd -set -uo pipefail -cd "$(dirname "$0")/../.." - -pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ - -Recipe 'minimal' \ - -NonInteractive \ - -Set @{ \ - agentName='min-azd-e2e'; \ - resourceGroup='rg-min-azd-e2e'; \ - location='swedencentral'; \ - targetRGs='aks-demo-app-cluster,rg-aks-journal' \ - } \ - -Output '/tmp/min-azd-e2e/'" - -# azd deploy -mkdir -p "./agents/min-azd-e2e" -cp -r /tmp/min-azd-e2e/* ./agents/min-azd-e2e/ 2>/dev/null || true -azd env select min-azd-e2e --no-prompt 2>/dev/null || azd env new min-azd-e2e --no-prompt -azd env set AZURE_AGENT_NAME min-azd-e2e --no-prompt -azd env set AZURE_RESOURCE_GROUP rg-min-azd-e2e --no-prompt -azd env set AZURE_LOCATION swedencentral --no-prompt -azd env set AZURE_SUBSCRIPTION_ID cbf44432-7f45-4906-a85d-d2b14a1e8328 --no-prompt -azd up --no-prompt - -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-min-azd-e2e' -AgentName 'min-azd-e2e'" - -# chat — save tastes -ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-min-azd-e2e -n min-azd-e2e --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS -X POST "$ENDPOINT/api/v1/threads" \ - -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' - -# wait for tastes.md -for i in $(seq 1 12); do - sleep 10 - TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) - if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then - break - fi -done - -# clone -pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'min-azd-e2e' -FromResourceGroup 'rg-min-azd-e2e' -AgentName 'min-azd-e2e-cl' -ResourceGroup 'rg-min-azd-e2e-cl' -Force" - -# verify clone + synth knowledge -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-min-azd-e2e-cl' -AgentName 'min-azd-e2e-cl'" -CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-min-azd-e2e-cl -n min-azd-e2e-cl --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-min-bicep-ps.sh b/sreagent-templates/tests/e2e-ps/test-min-bicep-ps.sh deleted file mode 100755 index 20eb36799..000000000 --- a/sreagent-templates/tests/e2e-ps/test-min-bicep-ps.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env bash -# E2E: minimal × bicep -set -uo pipefail -cd "$(dirname "$0")/../.." - -pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ - -Recipe 'minimal' \ - -NonInteractive \ - -Set @{ \ - agentName='min-bic-e2e'; \ - resourceGroup='rg-min-bic-e2e'; \ - location='swedencentral'; \ - targetRGs='rg-ebc-demo3' \ - } \ - -Output '/tmp/min-bic-e2e/'" - -pwsh -NoProfile -Command "& './bin/ps/Deploy-Agent.ps1' -InputPath '/tmp/min-bic-e2e' -Force" - -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-min-bic-e2e' -AgentName 'min-bic-e2e'" - -# chat — save tastes -ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-min-bic-e2e -n min-bic-e2e --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS -X POST "$ENDPOINT/api/v1/threads" \ - -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' - -# wait for tastes.md -for i in $(seq 1 12); do - sleep 10 - TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) - if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then - break - fi -done - -# clone -pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'min-bic-e2e' -FromResourceGroup 'rg-min-bic-e2e' -AgentName 'min-bic-e2e-cl' -ResourceGroup 'rg-min-bic-e2e-cl' -Force" - -# verify clone + synth knowledge -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-min-bic-e2e-cl' -AgentName 'min-bic-e2e-cl'" -CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-min-bic-e2e-cl -n min-bic-e2e-cl --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-min-tf-ps.sh b/sreagent-templates/tests/e2e-ps/test-min-tf-ps.sh deleted file mode 100755 index 7b1aefd1b..000000000 --- a/sreagent-templates/tests/e2e-ps/test-min-tf-ps.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env bash -# E2E: minimal × terraform -set -uo pipefail -cd "$(dirname "$0")/../.." - -pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ - -Recipe 'minimal' \ - -NonInteractive \ - -Set @{ \ - agentName='min-tf-e2e'; \ - resourceGroup='rg-min-tf-e2e'; \ - location='swedencentral'; \ - targetRGs='rg-contoso-swe,rg-groceryapp' \ - } \ - -Output '/tmp/min-tf-e2e/'" - -pwsh -NoProfile -Command "& './bin/ps/Deploy-Tf.ps1' -InputPath '/tmp/min-tf-e2e'" - -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-min-tf-e2e' -AgentName 'min-tf-e2e'" - -# chat — save tastes -ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-min-tf-e2e -n min-tf-e2e --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS -X POST "$ENDPOINT/api/v1/threads" \ - -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' - -# wait for tastes.md -for i in $(seq 1 12); do - sleep 10 - TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) - if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then - break - fi -done - -# clone -pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'min-tf-e2e' -FromResourceGroup 'rg-min-tf-e2e' -AgentName 'min-tf-e2e-cl' -ResourceGroup 'rg-min-tf-e2e-cl' -Backend 'terraform' -Force" - -# verify clone + synth knowledge -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-min-tf-e2e-cl' -AgentName 'min-tf-e2e-cl'" -CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-min-tf-e2e-cl -n min-tf-e2e-cl --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-pd-azd-ps.sh b/sreagent-templates/tests/e2e-ps/test-pd-azd-ps.sh deleted file mode 100755 index 6e43c636f..000000000 --- a/sreagent-templates/tests/e2e-ps/test-pd-azd-ps.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bash -# E2E: pagerduty-law-vmcosmos × azd -set -uo pipefail -cd "$(dirname "$0")/../.." - -pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ - -Recipe 'pagerduty-law-vmcosmos' \ - -NonInteractive \ - -Set @{ \ - agentName='pd-azd-e2e'; \ - resourceGroup='rg-pd-azd-e2e'; \ - location='swedencentral'; \ - targetRGs='rg-groceryapp'; \ - lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-ebc-demo3/providers/Microsoft.OperationalInsights/workspaces/law-ebc-demo3'; \ - pagerdutyApiKey='u+fake-pd-key' \ - } \ - -Output '/tmp/pd-azd-e2e/'" - -# azd deploy -mkdir -p "./agents/pd-azd-e2e" -cp -r /tmp/pd-azd-e2e/* ./agents/pd-azd-e2e/ 2>/dev/null || true -azd env select pd-azd-e2e --no-prompt 2>/dev/null || azd env new pd-azd-e2e --no-prompt -azd env set AZURE_AGENT_NAME pd-azd-e2e --no-prompt -azd env set AZURE_RESOURCE_GROUP rg-pd-azd-e2e --no-prompt -azd env set AZURE_LOCATION swedencentral --no-prompt -azd env set AZURE_SUBSCRIPTION_ID cbf44432-7f45-4906-a85d-d2b14a1e8328 --no-prompt -azd up --no-prompt - -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-pd-azd-e2e' -AgentName 'pd-azd-e2e'" - -# chat — save tastes -ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-pd-azd-e2e -n pd-azd-e2e --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS -X POST "$ENDPOINT/api/v1/threads" \ - -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' - -# wait for tastes.md -for i in $(seq 1 12); do - sleep 10 - TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) - if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then - break - fi -done - -# clone -pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'pd-azd-e2e' -FromResourceGroup 'rg-pd-azd-e2e' -AgentName 'pd-azd-e2e-cl' -ResourceGroup 'rg-pd-azd-e2e-cl' -Force" - -# verify clone + synth knowledge -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-pd-azd-e2e-cl' -AgentName 'pd-azd-e2e-cl'" -CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-pd-azd-e2e-cl -n pd-azd-e2e-cl --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-pd-bicep-ps.sh b/sreagent-templates/tests/e2e-ps/test-pd-bicep-ps.sh deleted file mode 100755 index 18c1a1325..000000000 --- a/sreagent-templates/tests/e2e-ps/test-pd-bicep-ps.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash -# E2E: pagerduty-law-vmcosmos × bicep -set -uo pipefail -cd "$(dirname "$0")/../.." - -pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ - -Recipe 'pagerduty-law-vmcosmos' \ - -NonInteractive \ - -Set @{ \ - agentName='pd-bic-e2e'; \ - resourceGroup='rg-pd-bic-e2e'; \ - location='swedencentral'; \ - targetRGs='rg-ebc-demo3,rg-contoso-eus2'; \ - lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-ebc-demo3/providers/Microsoft.OperationalInsights/workspaces/law-ebc-demo3'; \ - pagerdutyApiKey='u+fake-pd-key' \ - } \ - -Output '/tmp/pd-bic-e2e/'" - -pwsh -NoProfile -Command "& './bin/ps/Deploy-Agent.ps1' -InputPath '/tmp/pd-bic-e2e' -Force" - -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-pd-bic-e2e' -AgentName 'pd-bic-e2e'" - -# chat — save tastes -ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-pd-bic-e2e -n pd-bic-e2e --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS -X POST "$ENDPOINT/api/v1/threads" \ - -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' - -# wait for tastes.md -for i in $(seq 1 12); do - sleep 10 - TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) - if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then - break - fi -done - -# clone -pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'pd-bic-e2e' -FromResourceGroup 'rg-pd-bic-e2e' -AgentName 'pd-bic-e2e-cl' -ResourceGroup 'rg-pd-bic-e2e-cl' -Force" - -# verify clone + synth knowledge -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-pd-bic-e2e-cl' -AgentName 'pd-bic-e2e-cl'" -CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-pd-bic-e2e-cl -n pd-bic-e2e-cl --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true diff --git a/sreagent-templates/tests/e2e-ps/test-pd-tf-ps.sh b/sreagent-templates/tests/e2e-ps/test-pd-tf-ps.sh deleted file mode 100755 index eb0af11ef..000000000 --- a/sreagent-templates/tests/e2e-ps/test-pd-tf-ps.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash -# E2E: pagerduty-law-vmcosmos × terraform -set -uo pipefail -cd "$(dirname "$0")/../.." - -pwsh -NoProfile -Command "& './bin/ps/New-Agent.ps1' \ - -Recipe 'pagerduty-law-vmcosmos' \ - -NonInteractive \ - -Set @{ \ - agentName='pd-tf-e2e'; \ - resourceGroup='rg-pd-tf-e2e'; \ - location='swedencentral'; \ - targetRGs='aks-demo-app-cluster,rg-contoso-swe'; \ - lawId='/subscriptions/cbf44432-7f45-4906-a85d-d2b14a1e8328/resourceGroups/rg-contoso-swe/providers/Microsoft.OperationalInsights/workspaces/law-7defkiyvn3r44'; \ - pagerdutyApiKey='u+fake-pd-key' \ - } \ - -Output '/tmp/pd-tf-e2e/'" - -pwsh -NoProfile -Command "& './bin/ps/Deploy-Tf.ps1' -InputPath '/tmp/pd-tf-e2e'" - -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-pd-tf-e2e' -AgentName 'pd-tf-e2e'" - -# chat — save tastes -ENDPOINT=$(az resource show --resource-type "Microsoft.App/agents" -g rg-pd-tf-e2e -n pd-tf-e2e --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS -X POST "$ENDPOINT/api/v1/threads" \ - -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{"StartMessage":{"Text":"can you save my preferences to look at telemetry and understand problem before looking at sourcecode as my tastes file"}}' - -# wait for tastes.md -for i in $(seq 1 12); do - sleep 10 - TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) - if curl -sS "$ENDPOINT/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' 2>/dev/null; then - break - fi -done - -# clone -pwsh -NoProfile -Command "& './bin/ps/Clone-Agent.ps1' -FromAgent 'pd-tf-e2e' -FromResourceGroup 'rg-pd-tf-e2e' -AgentName 'pd-tf-e2e-cl' -ResourceGroup 'rg-pd-tf-e2e-cl' -Backend 'terraform' -Force" - -# verify clone + synth knowledge -pwsh -NoProfile -Command "& './bin/ps/Verify-Agent.ps1' -Subscription 'cbf44432-7f45-4906-a85d-d2b14a1e8328' -ResourceGroup 'rg-pd-tf-e2e-cl' -AgentName 'pd-tf-e2e-cl'" -CLONE_EP=$(az resource show --resource-type "Microsoft.App/agents" -g rg-pd-tf-e2e-cl -n pd-tf-e2e-cl --query "properties.agentEndpoint" -o tsv) -TOKEN=$(az account get-access-token --resource "https://azuresre.dev" --query accessToken -o tsv) -curl -sS "$CLONE_EP/api/v1/WorkspaceMemory/list?type=synthesized-knowledge" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.files[] | select(.path | test("tastes";"i"))' || true