ALFMOB-178 | Full Integration of Tests Creation and Executions, Metrics Evaluation and CI/CD Setup #41
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Alfie Melmac Test Automation | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: "0 3 * * *" # Every day at 3am UTC | |
| jobs: | |
| test: | |
| runs-on: macos-15 | |
| env: | |
| APP_URL: "https://github.com/Mindera/Alfie-UITests/releases/download/asdsad/Alfie.apk" | |
| APP_ZIP_URL: "https://github.com/Mindera/Alfie-UITests/releases/download/asdsad/Alfie.zip" | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v3 | |
| - name: Set up JDK | |
| uses: actions/setup-java@v3 | |
| with: | |
| distribution: "temurin" | |
| java-version: "17" | |
| - name: Set up Android SDK | |
| uses: android-actions/setup-android@v3 | |
| - name: List installed Xcode versions | |
| run: ls -l /Applications | grep Xcode | |
| - name: Install Android system image (arm64) | |
| run: sdkmanager "system-images;android-35;google_apis;arm64-v8a" | |
| - name: Create Android AVD (arm64) | |
| run: echo "no" | avdmanager create avd -n Medium_Phone_API_35 -k "system-images;android-35;google_apis;arm64-v8a" | |
| - name: List Android devices | |
| run: | | |
| echo "=== Emulator List ===" | |
| emulator -list-avds | |
| echo "=== AVD List ===" | |
| avdmanager list avd | |
| echo "=== Connected Devices ===" | |
| adb devices | |
| - name: Select Xcode version | |
| run: sudo xcode-select -s /Applications/Xcode_16.3.0.app/Contents/Developer | |
| - name: Show Xcode version | |
| run: xcodebuild -version | |
| - name: Show available iOS simulators | |
| run: xcrun simctl list devices | |
| - name: Generate Gradle Wrapper | |
| working-directory: Melmac | |
| run: | | |
| gradle wrapper --gradle-version 8.13 | |
| - name: Make Gradle Wrapper executable | |
| working-directory: Melmac | |
| run: | | |
| chmod +x gradlew | |
| - name: Build Melmac | |
| working-directory: Melmac | |
| run: | | |
| ./gradlew build | |
| - name: Prepare apps folder and download artifacts | |
| working-directory: Melmac | |
| run: | | |
| mkdir -p src/main/resources/apps | |
| echo "Downloading APK from $APP_URL" | |
| curl -L "$APP_URL" -o src/main/resources/apps/Alfie.apk | |
| echo "Downloading app bundle ZIP from $APP_ZIP_URL" | |
| curl -L "$APP_ZIP_URL" -o src/main/resources/apps/Alfie.zip | |
| cd src/main/resources/apps | |
| unzip -o Alfie.zip | |
| rm Alfie.zip | |
| echo "Listing contents of src/main/resources/apps:" | |
| ls -l | |
| - name: Start backend | |
| working-directory: Melmac | |
| env: | |
| CI: true | |
| run: ./gradlew run > $GITHUB_WORKSPACE/backend.log 2>&1 & | |
| - name: Tail backend logs in background | |
| working-directory: Melmac | |
| run: tail -F ../backend.log & | |
| - name: Wait for backend to be ready | |
| run: | | |
| for i in {1..30}; do # Wait up to 1 minute | |
| if curl -s http://localhost:8080/; then | |
| echo "Backend is up!" | |
| exit 0 | |
| fi | |
| sleep 2 | |
| done | |
| echo "Backend did not start in time" >&2 | |
| exit 1 | |
| - name: Debug backend process if startup fails | |
| if: failure() | |
| run: | | |
| echo "==== Java processes ====" | |
| ps aux | grep '[j]ava' || true | |
| echo "==== Ports in use ====" | |
| lsof -i :8080 || true | |
| echo "==== Backend logs ====" | |
| cat backend.log || echo "No backend.log file found" | |
| - name: Create test suite | |
| working-directory: Melmac | |
| run: | | |
| mkdir -p results | |
| curl -s -X POST http://localhost:8080/test-suites \ | |
| -H "Content-Type: application/json" \ | |
| -d '{ | |
| "testSuiteName": "My Test Suite", | |
| "testSuiteDescription": "Description of my test suite" | |
| }' | tee results/test_suite.json | |
| export TEST_SUITE_ID=$(jq '.testSuiteId' results/test_suite.json) | |
| echo "TEST_SUITE_ID=$TEST_SUITE_ID" >> $GITHUB_ENV | |
| - name: Create Android test plan | |
| working-directory: Melmac | |
| run: | | |
| curl -s -X POST http://localhost:8080/test-plans \ | |
| -H "Content-Type: application/json" \ | |
| -d "{ | |
| \"notes\": \"Test plan for App Startup Time metric\", | |
| \"testName\": \"Startup Time Plan\", | |
| \"metricMetricId\": 1, | |
| \"deviceName\": \"Medium_Phone_API_35\", | |
| \"appName\": \"Alfie.apk\", | |
| \"appVersion\": \"0.8.0\", | |
| \"appPackage\": \"au.com.alfie.ecomm.debug\", | |
| \"mainActivity\": \"au.com.alfie.ecomm.MainActivity\", | |
| \"executionTypeExecutionTypeId\": 1, | |
| \"thresholds\": [ | |
| { | |
| \"targetValue\": 100, | |
| \"thresholdTypeThresholdTypeId\": 2, | |
| \"metricOutputMetricOutputId\": 1 | |
| } | |
| ], | |
| \"metricParameters\": [ | |
| { | |
| \"parameterValue\": \"home-tab\", | |
| \"metricParameterMetricParameterId\": 1 | |
| } | |
| ], | |
| \"executionTypeParameters\": [], | |
| \"testSuiteVersionId\": ${TEST_SUITE_ID} | |
| }" | |
| - name: Create iOS test plan | |
| working-directory: Melmac | |
| run: | | |
| curl -s -X POST http://localhost:8080/test-plans \ | |
| -H "Content-Type: application/json" \ | |
| -d "{ | |
| \"notes\": \"Test plan for App Startup Time metric\", | |
| \"testName\": \"Startup Time Plan\", | |
| \"metricMetricId\": 1, | |
| \"deviceName\": \"iPhone 16 Pro\", | |
| \"appName\": \"Alfie.app\", | |
| \"appVersion\": \"0.8.1\", | |
| \"appPackage\": \"com.mindera.alfie.debug\", | |
| \"executionTypeExecutionTypeId\": 1, | |
| \"thresholds\": [ | |
| { | |
| \"targetValue\": 10000, | |
| \"thresholdTypeThresholdTypeId\": 1, | |
| \"metricOutputMetricOutputId\": 1 | |
| } | |
| ], | |
| \"metricParameters\": [ | |
| { | |
| \"parameterValue\": \"account-btn\", | |
| \"metricParameterMetricParameterId\": 1 | |
| }, | |
| { | |
| \"parameterValue\": \"50000\", | |
| \"metricParameterMetricParameterId\": 2 | |
| } | |
| ], | |
| \"executionTypeParameters\": [], | |
| \"testSuiteVersionId\": ${TEST_SUITE_ID} | |
| }" | |
| - name: Run full test suite | |
| working-directory: Melmac | |
| run: | | |
| mkdir -p results | |
| curl -X POST "http://localhost:8080/test-suites/${TEST_SUITE_ID}/run" > results/execution.json | |
| # --- Results summary generation in table format --- | |
| - name: Generate Markdown summary from suite results | |
| run: | | |
| mkdir -p results | |
| suiteExecutionId=$(jq '.suiteExecutionId' results/suite_execution.json) | |
| testSuiteVersionId=$(jq '.testSuiteVersionTestSuiteVersionId' results/suite_execution.json) | |
| echo "## Performance Test Suite Results" > results/summary.md | |
| echo "" >> results/summary.md | |
| echo "**Suite Execution ID:** $suiteExecutionId " >> results/summary.md | |
| echo "**Test Suite Version ID:** $testSuiteVersionId" >> results/summary.md | |
| echo "" >> results/summary.md | |
| echo "### Test Execution Results" >> results/summary.md | |
| echo "| Test Execution ID | Passed | Start Time | End Time | Test Plan Version ID |" >> results/summary.md | |
| echo "|-------------------|--------|------------|----------|----------------------|" >> results/summary.md | |
| jq -r '.executionResults[] | "| \(.testExecutionId) | \(.passed) | \(.initialTimestamp) | \(.endTimestamp) | \(.testPlanVersionTestPlanVersionId) |"' results/suite_execution.json >> results/summary.md | |
| echo "" >> results/summary.md | |
| # For each test execution, fetch and print thresholds and metric outputs | |
| jq -c '.executionResults[]' results/suite_execution.json | while read -r exec; do | |
| testExecutionId=$(echo "$exec" | jq '.testExecutionId') | |
| testPlanVersionId=$(echo "$exec" | jq '.testPlanVersionTestPlanVersionId') | |
| echo "#### Thresholds for Test Execution ID $testExecutionId" >> results/summary.md | |
| echo "| Target Value | Threshold Type | Metric Output ID |" >> results/summary.md | |
| echo "|--------------|---------------|------------------|" >> results/summary.md | |
| curl -s "http://localhost:8080/thresholds?testPlanVersionId=$testPlanVersionId" | jq -r '.[] | "| \(.targetValue) | \(.thresholdTypeThresholdTypeId) | \(.metricOutputMetricOutputId) |"' >> results/summary.md | |
| echo "" >> results/summary.md | |
| echo "#### Metric Output Results for Test Execution ID $testExecutionId" >> results/summary.md | |
| echo "| Metric Output Name | Value |" >> results/summary.md | |
| echo "|--------------------|-------|" >> results/summary.md | |
| curl -s "http://localhost:8080/test-executions/outputs?testExecutionId=$testExecutionId" | jq -r '.[] | "| \(.metricOutputName // "N/A") | \(.value // "N/A") |"' >> results/summary.md | |
| echo "" >> results/summary.md | |
| done | |
| echo "### Raw Suite Execution Result" >> results/summary.md | |
| jq . results/suite_execution.json >> results/summary.md | |
| - name: Upload test results artifact | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: performance-test-results | |
| path: results/summary.md | |
| - name: Add results to GitHub Actions summary | |
| if: always() | |
| run: | | |
| if [ -f results/summary.md ]; then | |
| cat results/summary.md >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "No summary file found." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Comment results on PR | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| let body = "No summary file found."; | |
| if (fs.existsSync('results/summary.md')) { | |
| body = fs.readFileSync('results/summary.md', 'utf8'); | |
| } | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: `### 📝 Performance Test Results\n\n${body}` | |
| }); | |
| - name: Upload backend log | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: backend-log | |
| path: backend.log |