Skip to content

Commit 833a628

Browse files
Merge branch 'dev' into main
2 parents 47c5190 + 9621cf4 commit 833a628

File tree

21 files changed

+5561
-17218
lines changed

21 files changed

+5561
-17218
lines changed

.flake8

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[flake8]
2-
max-line-length = 120
3-
exclude = .venv, _pycache_, migrations
4-
ignore = E501,F401,F811,F841,E203,E231,W503
2+
max-line-length = 88
3+
extend-ignore = E501
4+
exclude = venv, frontend
5+
ignore = E203, W503

.github/workflows/deploy.yml

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
name: CI-Validate Deployment
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
schedule:
8+
- cron: '0 6,18 * * *' # Runs at 6:00 AM and 6:00 PM GMT
9+
10+
jobs:
11+
deploy:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout Code
15+
uses: actions/checkout@v3
16+
17+
- name: Setup Azure CLI
18+
run: |
19+
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
20+
az --version # Verify installation
21+
22+
- name: Login to Azure
23+
run: |
24+
az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
25+
26+
- name: Install Bicep CLI
27+
run: az bicep install
28+
29+
- name: Generate Resource Group Name
30+
id: generate_rg_name
31+
run: |
32+
echo "Generating a unique resource group name..."
33+
TIMESTAMP=$(date +%Y%m%d%H%M%S)
34+
COMMON_PART="pslautomationRes"
35+
UNIQUE_RG_NAME="${COMMON_PART}${TIMESTAMP}"
36+
echo "RESOURCE_GROUP_NAME=${UNIQUE_RG_NAME}" >> $GITHUB_ENV
37+
echo "Generated Resource_GROUP_PREFIX: ${UNIQUE_RG_NAME}"
38+
39+
- name: Check and Create Resource Group
40+
id: check_create_rg
41+
run: |
42+
set -e
43+
echo "Checking if resource group exists..."
44+
rg_exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }})
45+
if [ "$rg_exists" = "false" ]; then
46+
echo "Resource group does not exist. Creating..."
47+
az group create --name ${{ env.RESOURCE_GROUP_NAME }} --location northcentralus || { echo "Error creating resource group"; exit 1; }
48+
else
49+
echo "Resource group already exists."
50+
fi
51+
52+
- name: Generate Unique Solution Prefix
53+
id: generate_solution_prefix
54+
run: |
55+
set -e
56+
COMMON_PART="pslr"
57+
TIMESTAMP=$(date +%s)
58+
UPDATED_TIMESTAMP=$(echo $TIMESTAMP | tail -c 3)
59+
UNIQUE_SOLUTION_PREFIX="${COMMON_PART}${UPDATED_TIMESTAMP}"
60+
echo "SOLUTION_PREFIX=${UNIQUE_SOLUTION_PREFIX}" >> $GITHUB_ENV
61+
echo "Generated SOLUTION_PREFIX: ${UNIQUE_SOLUTION_PREFIX}"
62+
63+
- name: Deploy Bicep Template
64+
id: deploy
65+
run: |
66+
set -e
67+
az deployment group create \
68+
--resource-group ${{ env.RESOURCE_GROUP_NAME }} \
69+
--template-file infrastructure/deployment.json \
70+
--parameters \
71+
HostingPlanName="${{ env.SOLUTION_PREFIX }}-plan" \
72+
ApplicationInsightsName="appins-${{ env.SOLUTION_PREFIX }}" \
73+
WebsiteName="webapp-${{ env.SOLUTION_PREFIX }}" \
74+
CosmosDBName="db-cosmos-${{ env.SOLUTION_PREFIX }}" \
75+
CosmosDBRegion="NorthCentralUS" \
76+
AzureSearchService="search-${{ env.SOLUTION_PREFIX }}" \
77+
AzureOpenAIResource="aoai-${{ env.SOLUTION_PREFIX }}" \
78+
WorkspaceName="worksp-${{ env.SOLUTION_PREFIX }}"
79+
80+
- name: Delete Bicep Deployment
81+
if: success()
82+
run: |
83+
set -e
84+
echo "Checking if resource group exists..."
85+
rg_exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }})
86+
if [ "$rg_exists" = "true" ]; then
87+
echo "Resource group exists. Cleaning..."
88+
az group delete \
89+
--name ${{ env.RESOURCE_GROUP_NAME }} \
90+
--yes \
91+
--no-wait
92+
echo "Resource group deleted... ${{ env.RESOURCE_GROUP_NAME }}"
93+
else
94+
echo "Resource group does not exist."
95+
fi
96+
97+
- name: Wait for Resource Deletion to Complete
98+
run: |
99+
# List of resources to check based on SOLUTION_PREFIX
100+
resources_to_check=(
101+
"aoai-${{ env.SOLUTION_PREFIX }}"
102+
"appins-${{ env.SOLUTION_PREFIX }}"
103+
"db-cosmos-${{ env.SOLUTION_PREFIX }}"
104+
"${{ env.SOLUTION_PREFIX }}-plan"
105+
"search-${{ env.SOLUTION_PREFIX }}"
106+
"webapp-${{ env.SOLUTION_PREFIX }}"
107+
"worksp-${{ env.SOLUTION_PREFIX }}"
108+
)
109+
110+
# Get the list of resources in YAML format
111+
resource_list=$(az resource list --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} --output yaml)
112+
113+
# Maximum number of retries and retry intervals
114+
max_retries=3
115+
retry_intervals=(30 60 120)
116+
retries=0
117+
118+
while true; do
119+
resource_found=false
120+
# Iterate through the resources to check
121+
for resource in "${resources_to_check[@]}"; do
122+
echo "Checking resource: $resource"
123+
if echo "$resource_list" | grep -q "name: $resource"; then
124+
echo "Resource '$resource' exists in the subscription."
125+
resource_found=true
126+
else
127+
echo "Resource '$resource' does not exist in the subscription."
128+
fi
129+
done
130+
131+
# If any resource exists, retry
132+
if [ "$resource_found" = true ]; then
133+
retries=$((retries + 1))
134+
if [ "$retries" -ge "$max_retries" ]; then
135+
echo "Maximum retry attempts reached. Exiting."
136+
break
137+
else
138+
echo "Waiting for ${retry_intervals[$retries-1]} seconds before retrying..."
139+
sleep ${retry_intervals[$retries-1]}
140+
fi
141+
else
142+
echo "No resources found. Exiting."
143+
break
144+
fi
145+
done
146+
147+
- name: Purging the Resources
148+
if: success()
149+
run: |
150+
set -e
151+
# Purging resources based on solution prefix
152+
echo "Purging resources..."
153+
154+
# List of resources to purge
155+
resources_to_purge=(
156+
"aoai-${{ env.SOLUTION_PREFIX }}"
157+
"appins-${{ env.SOLUTION_PREFIX }}"
158+
"db-cosmos-${{ env.SOLUTION_PREFIX }}"
159+
"${{ env.SOLUTION_PREFIX }}-plan"
160+
"search-${{ env.SOLUTION_PREFIX }}"
161+
"webapp-${{ env.SOLUTION_PREFIX }}"
162+
"worksp-${{ env.SOLUTION_PREFIX }}"
163+
)
164+
165+
for resource in "${resources_to_purge[@]}"; do
166+
echo "Purging resource: $resource"
167+
if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/uksouth/deletedAccounts/$resource --verbose; then
168+
echo "Failed to purge resource: $resource"
169+
else
170+
echo "Purged the resource: $resource"
171+
fi
172+
done
173+
174+
echo "Resource purging completed successfully"
175+
176+
- name: Send Notification on Failure
177+
if: failure()
178+
run: |
179+
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
180+
181+
EMAIL_BODY=$(cat <<EOF
182+
{
183+
"body": "<p>Dear Team,</p><p>We would like to inform you that the Research Assistant Automation process has encountered an issue and has failed to complete successfully.</p><p><strong>Build URL:</strong> ${RUN_URL}<br> ${OUTPUT}</p><p>Please investigate the matter at your earliest convenience.</p><p>Best regards,<br>Your Automation Team</p>"
184+
}
185+
EOF
186+
)
187+
188+
curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
189+
-H "Content-Type: application/json" \
190+
-d "$EMAIL_BODY" || echo "Failed to send notification"

.github/workflows/docker-build-and-push.yml

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ on:
55
types: [closed]
66
branches:
77
- main
8+
- dev
9+
- demo
810
workflow_dispatch: # Add this line to enable manual triggering
911

1012
jobs:
@@ -20,13 +22,40 @@ jobs:
2022
uses: docker/setup-buildx-action@v1
2123

2224
- name: Log in to Azure Container Registry
23-
uses: azure/docker-login@v1
25+
if: ${{ github.ref_name == 'main' }}
26+
uses: azure/docker-login@v2
2427
with:
2528
login-server: ${{ secrets.ACR_LOGIN_SERVER }}
2629
username: ${{ secrets.ACR_USERNAME }}
2730
password: ${{ secrets.ACR_PASSWORD }}
2831

32+
- name: Log in to Azure Container Registry (Dev/Demo)
33+
if: ${{ github.ref_name == 'dev' || github.ref_name == 'demo' }}
34+
uses: azure/docker-login@v2
35+
with:
36+
login-server: ${{ secrets.ACR_DEV_LOGIN_SERVER }}
37+
username: ${{ secrets.ACR_DEV_USERNAME }}
38+
password: ${{ secrets.ACR_DEV_PASSWORD }}
39+
40+
- name: Set Docker image tag
41+
id: docker_tag
42+
run: |
43+
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
44+
echo "TAG=latest" >> $GITHUB_ENV
45+
elif [[ "${{ github.ref }}" == "refs/heads/dev" ]]; then
46+
echo "TAG=dev" >> $GITHUB_ENV
47+
elif [[ "${{ github.ref }}" == "refs/heads/demo" ]]; then
48+
echo "TAG=demo" >> $GITHUB_ENV
49+
fi
50+
2951
- name: Build and push Docker image
52+
if: ${{ github.ref_name == 'main' }}
53+
run: |
54+
docker build -t ${{ secrets.ACR_LOGIN_SERVER }}/webapp:${{ env.TAG }} -f WebApp.Dockerfile .
55+
docker push ${{ secrets.ACR_LOGIN_SERVER }}/webapp:${{ env.TAG }}
56+
57+
- name: Build and push Docker image (Dev/Demo)
58+
if: ${{ github.ref_name == 'dev' || github.ref_name == 'demo' }}
3059
run: |
3160
docker build -t ${{ secrets.ACR_LOGIN_SERVER }}/webapp:latest -f WebApp.Dockerfile .
3261
docker push ${{ secrets.ACR_LOGIN_SERVER }}/webapp:latest

.github/workflows/pylint.yml

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,14 @@ jobs:
2020
with:
2121
python-version: ${{ matrix.python-version }}
2222

23-
# Step 3: Run all code quality checks
24-
- name: Run Code Quality Checks
23+
- name: Install dependencies
2524
run: |
2625
python -m pip install --upgrade pip
27-
pip install -r requirements.txt
28-
echo "Fixing imports with Isort..."
29-
python -m isort --verbose .
30-
echo "Formatting code with Black..."
31-
python -m black --verbose .
32-
echo "Running Flake8..."
33-
python -m flake8 --config=.flake8 --verbose .
26+
pip install -r requirements-dev.txt
27+
28+
# Step 3: Run all code quality checks
29+
- name: Pylint
30+
run: |
3431
echo "Running Pylint..."
35-
python -m pylint --rcfile=.pylintrc --verbose .
32+
python -m flake8 --config=.flake8 --verbose .
33+

.github/workflows/tests.yml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- main # Trigger on push to the main branch
7+
pull_request:
8+
branches:
9+
- main # Trigger on pull requests to the main branch
10+
types:
11+
- opened
12+
- ready_for_review
13+
- reopened
14+
- synchronize
15+
16+
jobs:
17+
backend_tests:
18+
name: Backend Tests
19+
runs-on: ubuntu-latest # Use the latest Ubuntu runner
20+
21+
steps:
22+
- uses: actions/checkout@v4 # Checkout the repository
23+
24+
# Set up Python environment for Backend
25+
- name: Set up Python
26+
uses: actions/setup-python@v5
27+
with:
28+
python-version: "3.11" # Set Python version
29+
30+
- name: Install Backend Dependencies
31+
run: |
32+
python -m pip install -r requirements.txt
33+
python -m pip install coverage pytest-cov
34+
python -m pip install azure-keyvault-secrets
35+
36+
- name: Run Backend Tests with Coverage
37+
run: |
38+
if python -m pytest --cov=. --cov-report=xml --cov-report=html --cov-report=term-missing --junitxml=coverage-junit.xml; then
39+
echo "Tests completed, checking coverage."
40+
# Only fail if coverage does not meet criteria
41+
if [ -f coverage.xml ]; then
42+
COVERAGE=$(python -c "import xml.etree.ElementTree as ET; tree = ET.parse('coverage.xml'); root = tree.getroot(); coverage = root.find('coverage').get('lines').split('%')[0]; print(float(coverage))")
43+
if (( $(echo "$COVERAGE < 80" | bc -l) )); then
44+
echo "Coverage is below 80%, failing the job."
45+
exit 1
46+
fi
47+
fi
48+
else
49+
echo "No tests found, skipping coverage check."
50+
fi
51+
52+
- uses: actions/upload-artifact@v4
53+
with:
54+
name: backend-coverage
55+
path: |
56+
coverage.xml # Correct path to backend coverage
57+
coverage-junit.xml # Correct path to backend JUnit report
58+
htmlcov/ # Correct path to backend HTML coverage report
59+
60+
frontend_tests:
61+
name: Frontend Tests
62+
runs-on: ubuntu-latest # Use the latest Ubuntu runner
63+
64+
steps:
65+
- uses: actions/checkout@v4 # Checkout the repository
66+
67+
# Set up Node.js environment for Frontend
68+
- name: Set up Node.js
69+
uses: actions/setup-node@v3
70+
with:
71+
node-version: '20' # Set the Node.js version
72+
73+
- name: Cache npm dependencies
74+
uses: actions/cache@v3
75+
with:
76+
path: ~/.npm
77+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
78+
restore-keys: |
79+
${{ runner.os }}-node-
80+
81+
- name: Navigate to frontend directory
82+
run: cd frontend
83+
84+
- name: Install Frontend Dependencies
85+
run: |
86+
cd frontend # Change to the frontend directory
87+
npm install # Install dependencies from frontend/package.json
88+
89+
- name: Run Frontend Tests with Coverage
90+
run: |
91+
cd frontend # Change to the frontend directory
92+
if npm run test -- --coverage; then
93+
echo "Tests completed, checking coverage."
94+
# Check coverage report and ensure it meets threshold
95+
if [ -f frontend/coverage/lcov-report/index.html ]; then
96+
COVERAGE=$(cat frontend/coverage/lcov-report/index.html | grep -oP 'total: \K[0-9]+(\.[0-9]+)?')
97+
if (( $(echo "$COVERAGE < 80" | bc -l) )); then
98+
echo "Coverage is below 80%, failing the job."
99+
exit 1
100+
fi
101+
fi
102+
else
103+
echo "No tests found, skipping coverage check."
104+
fi
105+
106+
- uses: actions/upload-artifact@v4
107+
with:
108+
name: frontend-coverage
109+
path: |
110+
frontend/coverage/ # Correct path to frontend coverage
111+
frontend/coverage/lcov-report/ # Correct path to frontend lcov report

0 commit comments

Comments
 (0)