Skip to content
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 177 additions & 0 deletions .github/workflows/building-comfort.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# Copyright 2025 The Drasi Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Building Comfort E2E Test

on:
push:
branches:
- e2e-framework-automation
Copy link

Copilot AI Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow is configured to trigger on pushes to a feature branch 'e2e-framework-automation'. This should be updated to trigger on appropriate branches like 'main' or 'develop' for production use, or removed if this was only for development testing.

Suggested change
push:
branches:
- e2e-framework-automation
- main
- develop

Copilot uses AI. Check for mistakes.

workflow_dispatch:
repository_dispatch:
types: [building-comfort-trigger]

permissions:
contents: read
id-token: write

env:
CLUSTER_NAME_REDIS: "building-comfort-aks-${{ github.run_number }}-redis"
CLUSTER_NAME_ROCKS: "building-comfort-aks-${{ github.run_number }}-rocks"
CLUSTER_NAME_MEMORY: "building-comfort-aks-${{ github.run_number }}-memory"
RESOURCE_GROUP_NAME: "project-drasi"

jobs:
infra:
runs-on: ubuntu-latest
strategy:
matrix:
cluster_type: [redis, rocks, memory]

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Azure Login
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

- name: Deploy AKS cluster
run: |
az deployment group create \
--resource-group ${{ env.RESOURCE_GROUP_NAME }} \
--template-file infra/aks/aks-cluster.bicep \
--parameters clusterName="building-comfort-aks-${{ github.run_number }}-${{ matrix.cluster_type }}" \
--name "aks-cluster-${{ github.run_number }}-${{ matrix.cluster_type }}"

deploy-tests:
runs-on: ubuntu-latest
needs: infra
strategy:
matrix:
cluster_type: [redis, rocks, memory]

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Azure Login
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

- name: Get AKS credentials
run: |
az aks get-credentials \
--resource-group ${{ env.RESOURCE_GROUP_NAME }} \
--name "building-comfort-aks-${{ github.run_number }}-${{ matrix.cluster_type }}" \
--overwrite-existing


- name: Install Drasi CLI
run: |
curl -fsSL https://raw.githubusercontent.com/drasi-project/drasi-platform/main/cli/installers/install-drasi-cli.sh | /bin/bash


- name: Deploy building comfort tests
run: |
cd e2e-test-framework
./examples/building_comfort/drasi/run_test_with_${{ matrix.cluster_type }}.sh

sleep 10

# Wait for tests to complete by polling the query status
echo "Waiting for tests to complete..."
while true; do

# Check query status
RESPONSE=$(curl -s "http://localhost:63123/test_run_host/queries/github_dev_repo.building_comfort.test_run_001.room-comfort-level")
echo "API Response: $RESPONSE"

STATUS=$(echo "$RESPONSE" | jq -r '.query_observer.status // "Running"')
echo "Current status: $STATUS"
if [ "$STATUS" = "Stopped" ]; then
echo "Tests completed successfully!"
break
fi

echo "Tests still running, waiting 10 seconds..."
sleep 10
done

- name: Export test results
run: |
cd e2e-test-framework
./examples/building_comfort/drasi/get_test_run_results.sh "building-comfort-aks-${{ github.run_number }}-${{ matrix.cluster_type }}"

- name: Re-authenticate with Azure (refresh token)
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

- name: Upload test results to storage account
run: |
cd e2e-test-framework
CLUSTER_NAME="building-comfort-aks-${{ github.run_number }}-${{ matrix.cluster_type }}"
CONTAINER_NAME="test-results"
STORAGE_ACCOUNT="drasidev"

# Create container if it doesn't exist
az storage container create \
--name $CONTAINER_NAME \
--account-name $STORAGE_ACCOUNT \
--auth-mode login \
--only-show-errors

# Upload all files from the results directory with Cold tier
az storage blob upload-batch \
--destination $CONTAINER_NAME \
--source "./$CLUSTER_NAME" \
--destination-path "building-comfort/$CLUSTER_NAME" \
--account-name $STORAGE_ACCOUNT \
--auth-mode login \
--tier Cold



Copy link

Copilot AI Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty lines with trailing whitespace should be removed to maintain clean code formatting.

Copilot uses AI. Check for mistakes.

# cleanup:
# runs-on: ubuntu-latest
# needs: deploy-tests
# if: always()
# strategy:
# matrix:
# cluster_type: [redis, rocks, memory]

# steps:
# - name: Azure Login
# uses: azure/login@v2
# with:
# client-id: ${{ secrets.AZURE_CLIENT_ID }}
# tenant-id: ${{ secrets.AZURE_TENANT_ID }}
# subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

# - name: Delete AKS cluster
# run: |
# az aks delete \
# --resource-group ${{ env.RESOURCE_GROUP_NAME }} \
# --name "building-comfort-aks-${{ github.run_number }}-${{ matrix.cluster_type }}" \
# --yes --no-wait

Copy link

Copilot AI Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commented cleanup job should either be removed or uncommented with proper documentation explaining why it's disabled. Leaving commented code in production workflows reduces maintainability and creates confusion about intended behavior.

Suggested change
# cleanup:
# runs-on: ubuntu-latest
# needs: deploy-tests
# if: always()
# strategy:
# matrix:
# cluster_type: [redis, rocks, memory]
# steps:
# - name: Azure Login
# uses: azure/login@v2
# with:
# client-id: ${{ secrets.AZURE_CLIENT_ID }}
# tenant-id: ${{ secrets.AZURE_TENANT_ID }}
# subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
# - name: Delete AKS cluster
# run: |
# az aks delete \
# --resource-group ${{ env.RESOURCE_GROUP_NAME }} \
# --name "building-comfort-aks-${{ github.run_number }}-${{ matrix.cluster_type }}" \
# --yes --no-wait

Copilot uses AI. Check for mistakes.

32 changes: 18 additions & 14 deletions .github/workflows/draft-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ on:
image_prefix:
description: 'Image Prefix'
required: false
default: 'ghcr.io/drasi-project'
default: 'ghcr.io/drasi-project'
repository_dispatch:
types: [draft-release-trigger]

permissions:
id-token: write # Required for requesting the JWT
Expand All @@ -32,6 +34,8 @@ permissions:

env:
RELEASE_PATH: ./release
TAG: ${{ github.event.client_payload.tag || inputs.tag }}
IMAGE_PREFIX: ${{ github.event.client_payload.image_prefix || inputs.image_prefix }}

TEST_INFRA_COMPONENTS: '[
{"label": "E2E proxy", "path": "e2e-test-framework/proxy", "name": "e2e-proxy", "platforms": "linux/amd64,linux/arm64"},
Expand Down Expand Up @@ -94,8 +98,8 @@ jobs:
if: contains(matrix.component.platforms, steps.platform.outputs.platform)
run: |
cd ${{ matrix.component.path }}
DOCKER_TAG_VERSION=${{ inputs.tag }}${{ steps.platform.outputs.suffix }} \
IMAGE_PREFIX=${{ inputs.image_prefix }} \
DOCKER_TAG_VERSION=${{ env.TAG }}${{ steps.platform.outputs.suffix }} \
IMAGE_PREFIX=${{ env.IMAGE_PREFIX }} \
DOCKERX_OPTS="--push --platform ${{ steps.platform.outputs.platform }}" \
make

Expand All @@ -117,32 +121,32 @@ jobs:
expected_platforms=$(echo '${{ env.TEST_INFRA_COMPONENTS }}' | jq -r ".[] | select(.name == \"$component\") | .platforms")
if echo "$expected_platforms" | grep -q "linux/amd64"; then

if docker manifest inspect ghcr.io/drasi-project/$component:${{ inputs.tag }}-amd64 > /dev/null 2>&1; then
echo "Manifest for $component:${{ inputs.tag }}-amd64:"
docker manifest inspect ghcr.io/drasi-project/$component:${{ inputs.tag }}-amd64
manifests+=("ghcr.io/drasi-project/$component:${{ inputs.tag }}-amd64")
if docker manifest inspect ${{ env.IMAGE_PREFIX }}/$component:${{ env.TAG }}-amd64 > /dev/null 2>&1; then
echo "Manifest for $component:${{ env.TAG }}-amd64:"
docker manifest inspect ${{ env.IMAGE_PREFIX }}/$component:${{ env.TAG }}-amd64
manifests+=("${{ env.IMAGE_PREFIX }}/$component:${{ env.TAG }}-amd64")

else
echo "Error: Expected amd64 manifest not found for $component:${{ inputs.tag }}-amd64" >&2
echo "Error: Expected amd64 manifest not found for $component:${{ env.TAG }}-amd64" >&2
exit 1
fi
fi

if echo "$expected_platforms" | grep -q "linux/arm64"; then

if docker manifest inspect ghcr.io/drasi-project/$component:${{ inputs.tag }}-arm64 > /dev/null 2>&1; then
echo "Manifest for $component:${{ inputs.tag }}-arm64:"
docker manifest inspect ghcr.io/drasi-project/$component:${{ inputs.tag }}-arm64
manifests+=("ghcr.io/drasi-project/$component:${{ inputs.tag }}-arm64")
if docker manifest inspect ${{ env.IMAGE_PREFIX }}/$component:${{ env.TAG }}-arm64 > /dev/null 2>&1; then
echo "Manifest for $component:${{ env.TAG }}-arm64:"
docker manifest inspect ${{ env.IMAGE_PREFIX }}/$component:${{ env.TAG }}-arm64
manifests+=("${{ env.IMAGE_PREFIX }}/$component:${{ env.TAG }}-arm64")

else
echo "Error: Expected arm64 manifest not found for $component:${{ inputs.tag }}-arm64" >&2
echo "Error: Expected arm64 manifest not found for $component:${{ env.TAG }}-arm64" >&2
exit 1
fi
fi

if [ ${#manifests[@]} -gt 0 ]; then
docker buildx imagetools create -t ghcr.io/drasi-project/$component:${{ inputs.tag }} ${manifests[@]}
docker buildx imagetools create -t ${{ env.IMAGE_PREFIX }}/$component:${{ env.TAG }} ${manifests[@]}
else
echo "No manifests found for $component, skipping manifest creation."
fi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,20 @@ if [ -z "$POD_NAME" ]; then
fi

# Source
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/az_dev_repo.building_comfort.test_run_001/sources/facilities-db/test_run_summary.json" "./${TEST_RUN_ID}/source_summary.json"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/github_dev_repo.building_comfort.test_run_001/sources/facilities-db/test_run_summary.json" "./${TEST_RUN_ID}/source_summary.json"

# Query Observer
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/az_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/test_run_summary.json" "./${TEST_RUN_ID}/query_summary.json"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/github_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/test_run_summary.json" "./${TEST_RUN_ID}/query_summary.json"

# Query Result Profiler
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/az_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/summary.json" "./${TEST_RUN_ID}/query_profiler_summary.json"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/github_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/summary.json" "./${TEST_RUN_ID}/query_profiler_summary.json"

kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/az_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_all_abs.png" "./${TEST_RUN_ID}/query_profiler_viz_all_abs.png"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/az_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_all_rel.png" "./${TEST_RUN_ID}/query_profiler_viz_all_rel.png"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/az_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_drasi_only_abs.png" "./${TEST_RUN_ID}/query_profiler_viz_drasi_only_abs.png"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/az_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_drasi_only_rel.png" "./${TEST_RUN_ID}/query_profiler_viz_drasi_only_rel.png"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/github_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_all_abs.png" "./${TEST_RUN_ID}/query_profiler_viz_all_abs.png"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/github_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_all_rel.png" "./${TEST_RUN_ID}/query_profiler_viz_all_rel.png"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/github_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_drasi_only_abs.png" "./${TEST_RUN_ID}/query_profiler_viz_drasi_only_abs.png"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/github_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_drasi_only_rel.png" "./${TEST_RUN_ID}/query_profiler_viz_drasi_only_rel.png"

kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/az_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_rates.csv" "./${TEST_RUN_ID}/query_profiler_change_rates.csv"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/az_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_distributions.csv" "./${TEST_RUN_ID}/query_profiler_change_distributions.csv"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/github_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_rates.csv" "./${TEST_RUN_ID}/query_profiler_change_rates.csv"
kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/github_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_distributions.csv" "./${TEST_RUN_ID}/query_profiler_change_distributions.csv"

# kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/az_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_00000.jsonl" "./${TEST_RUN_ID}/query_profiler_change_log_sample.jsonl"
# kubectl cp -c "$CONTAINER" "$NAMESPACE/$POD_NAME:/drasi_data_store/test_runs/github_dev_repo.building_comfort.test_run_001/queries/room-comfort-level/result_stream_log/profiler/change_00000.jsonl" "./${TEST_RUN_ID}/query_profiler_change_log_sample.jsonl"
42 changes: 42 additions & 0 deletions infra/aks/aks-cluster.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
@description('The name of the AKS cluster')
param clusterName string

@description('The location of the AKS cluster')
param location string = 'westus3'

@description('Optional DNS prefix to use with hosted Kubernetes API server FQDN')
param dnsPrefix string = 'drasi-aks-${uniqueString(resourceGroup().id)}'

@description('The number of nodes for the system pool')
param systemNodeCount int = 2

@description('The size of the Virtual Machine')
param vmSize string = 'Standard_D8ds_v5'

resource aks 'Microsoft.ContainerService/managedClusters@2024-02-01' = {
name: clusterName
location: location
identity: {
type: 'SystemAssigned'
}
properties: {
dnsPrefix: dnsPrefix
autoUpgradeProfile: {
nodeOSUpgradeChannel: 'NodeImage'
upgradeChannel: 'stable'
}
agentPoolProfiles: [
{
name: 'agentpool'
count: systemNodeCount
vmSize: vmSize
osType: 'Linux'
osSKU: 'AzureLinux'
mode: 'System'
type: 'VirtualMachineScaleSets'
}
]
}
}

output controlPlaneFQDN string = aks.properties.fqdn
Loading