Skip to content

Fix: consumption SKU agent runAfter bug β€” restore runAfter when re-adding agent loop #106

Fix: consumption SKU agent runAfter bug β€” restore runAfter when re-adding agent loop

Fix: consumption SKU agent runAfter bug β€” restore runAfter when re-adding agent loop #106

Workflow file for this run

name: PR Coverage Check
on:
pull_request:
branches: [main, dev/*, hotfix/*]
jobs:
coverage:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Cache turbo build setup
uses: actions/cache@v4
with:
path: .turbo
key: ${{ runner.os }}-turbo-${{ github.sha }}
restore-keys: |
${{ runner.os }}-turbo-
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: 9.1.3
run_install: |
- recursive: true
args: [--frozen-lockfile, --strict-peer-dependencies]
- name: Build
run: pnpm turbo run build --cache-dir=.turbo
- name: Run tests with coverage
run: |
pnpm turbo run test:lib --cache-dir=.turbo
pnpm turbo run test:iframe-app --cache-dir=.turbo
pnpm turbo run test:extension-unit --cache-dir=.turbo
- name: Merge coverage reports
run: |
mkdir -p coverage
# Find all lcov.info files and merge them
find . -path ./node_modules -prune -o -name 'lcov.info' -print 2>/dev/null | head -20 > lcov-files.txt
if [ -s lcov-files.txt ]; then
npx lcov-result-merger './libs/**/coverage/lcov.info' './apps/**/coverage/lcov.info' ./coverage/lcov.info || true
fi
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v46
with:
files: |
**/*.ts
**/*.tsx
files_ignore: |
# Test files
**/*.test.ts
**/*.test.tsx
**/*.spec.ts
**/*.spec.tsx
**/__test__/**
**/__tests__/**
**/__mocks__/**
**/test-setup.ts
**/test-globals.ts
**/setup.ts
# Type definitions and models
**/*.d.ts
**/models/**
**/types/**
**/interfaces/**
**/*Types.ts
**/*Types.tsx
**/*Model.ts
**/*Models.ts
**/*Interface.ts
**/*Interfaces.ts
**/types.ts
**/types.tsx
**/styles.ts
**/constants.ts
**/constants/**
# Config files
**/*.config.ts
**/*.config.tsx
**/vite.config.*
**/vitest.config.*
**/tsconfig.*
# Index/barrel files (just re-exports)
**/index.ts
**/index.tsx
# Node modules and build output
**/node_modules/**
**/dist/**
**/build/**
# Standalone app (dev environment, not covered by tests)
apps/Standalone/**
# Documentation site
apps/docs/**
# Manifest and swagger files (configuration/data, not logic)
**/manifest/**
**/manifests/**
**/swagger/**
# Service interfaces and base classes (tested via implementations)
**/designer-client-services/lib/*.ts
**/lib/base/**
# Environment-specific service index/barrel files
**/lib/consumption/index.ts
**/lib/standard/index.ts
# Static operation and schema definitions
**/operations/**
**/schemas/**
**/staticresultschema/**
# Application setup and providers (not business logic)
**/*Context.ts
**/*Context.tsx
**/*Provider.ts
**/*Provider.tsx
**/providers/**
- name: Check coverage on changed files
id: coverage-check
run: |
echo "## πŸ“Š Coverage Report for Changed Files" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Get the list of changed source files
CHANGED_FILES="${{ steps.changed-files.outputs.all_changed_files }}"
if [ -z "$CHANGED_FILES" ]; then
echo "No source files changed in this PR." >> $GITHUB_STEP_SUMMARY
echo "coverage_status=skip" >> $GITHUB_OUTPUT
exit 0
fi
echo "### Changed Files:" >> $GITHUB_STEP_SUMMARY
for file in $CHANGED_FILES; do
echo "- \`$file\`" >> $GITHUB_STEP_SUMMARY
done
echo "" >> $GITHUB_STEP_SUMMARY
# Check if coverage file exists
if [ ! -f "./coverage/lcov.info" ]; then
echo "⚠️ No merged coverage report found. Checking individual coverage files..." >> $GITHUB_STEP_SUMMARY
# Look for individual coverage files
COVERAGE_FILES=$(find . -path ./node_modules -prune -o -name 'lcov.info' -print 2>/dev/null | grep -v node_modules || true)
if [ -z "$COVERAGE_FILES" ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "❌ **No coverage data found.** Please ensure tests generate coverage reports." >> $GITHUB_STEP_SUMMARY
echo "coverage_status=no_data" >> $GITHUB_OUTPUT
exit 0
fi
fi
# Parse coverage and check changed files
UNCOVERED_FILES=""
COVERED_FILES=""
PARTIAL_FILES=""
SKIPPED_FILES=""
# Define packages that require coverage (libs with vitest configs)
COVERED_PACKAGES="libs/designer libs/designer-ui libs/designer-v2 libs/logic-apps-shared libs/data-mapper libs/data-mapper-v2 libs/chatbot libs/a2a-core libs/vscode-extension apps/vs-code-designer apps/vs-code-react apps/iframe-app"
for file in $CHANGED_FILES; do
# Skip if file doesn't exist (might have been deleted)
if [ ! -f "$file" ]; then
continue
fi
# Find the corresponding coverage file for this source file
# Look in the package's coverage directory
PKG_DIR=$(echo "$file" | sed 's|/src/.*||')
LCOV_FILE="$PKG_DIR/coverage/lcov.info"
# Check if this package requires coverage
PKG_REQUIRES_COVERAGE=false
for pkg in $COVERED_PACKAGES; do
if [ "$PKG_DIR" = "$pkg" ]; then
PKG_REQUIRES_COVERAGE=true
break
fi
done
if [ -f "$LCOV_FILE" ]; then
# Get the absolute path pattern to match in lcov (lcov uses paths relative to package root or absolute)
# Extract the path after PKG_DIR to match against lcov SF entries
FILE_RELATIVE_PATH=$(echo "$file" | sed "s|^$PKG_DIR/||")
# Check if this file is mentioned in the coverage report using the relative path
if grep -q "SF:.*${FILE_RELATIVE_PATH}$" "$LCOV_FILE" 2>/dev/null; then
# Get line coverage for this file - use the full relative path for accurate matching
FILE_SECTION=$(awk "/SF:.*${FILE_RELATIVE_PATH//\//\\/}\$/,/end_of_record/" "$LCOV_FILE" 2>/dev/null || true)
if [ -n "$FILE_SECTION" ]; then
LINES_FOUND=$(echo "$FILE_SECTION" | grep "^LF:" | cut -d: -f2 || echo "0")
LINES_HIT=$(echo "$FILE_SECTION" | grep "^LH:" | cut -d: -f2 || echo "0")
if [ "$LINES_FOUND" -gt 0 ] 2>/dev/null; then
COVERAGE_PCT=$((LINES_HIT * 100 / LINES_FOUND))
if [ "$COVERAGE_PCT" -ge 80 ]; then
COVERED_FILES="$COVERED_FILES\nβœ… \`$file\` - ${COVERAGE_PCT}% covered"
elif [ "$COVERAGE_PCT" -gt 0 ]; then
PARTIAL_FILES="$PARTIAL_FILES\n⚠️ \`$file\` - ${COVERAGE_PCT}% covered (needs improvement)"
else
UNCOVERED_FILES="$UNCOVERED_FILES\n❌ \`$file\` - 0% covered"
fi
fi
fi
else
UNCOVERED_FILES="$UNCOVERED_FILES\n❌ \`$file\` - Not covered by tests"
fi
elif [ "$PKG_REQUIRES_COVERAGE" = true ]; then
# Package should have coverage but doesn't - this is a problem
UNCOVERED_FILES="$UNCOVERED_FILES\n❌ \`$file\` - No coverage data (package should have tests)"
else
# Package doesn't require coverage (not in the list)
SKIPPED_FILES="$SKIPPED_FILES\n⏭️ \`$file\` - Package not configured for coverage"
fi
done
echo "### Coverage Results:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ -n "$COVERED_FILES" ]; then
echo "#### βœ… Well Covered:" >> $GITHUB_STEP_SUMMARY
echo -e "$COVERED_FILES" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi
if [ -n "$PARTIAL_FILES" ]; then
echo "#### ⚠️ Partially Covered (< 80%):" >> $GITHUB_STEP_SUMMARY
echo -e "$PARTIAL_FILES" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi
if [ -n "$SKIPPED_FILES" ]; then
echo "#### ⏭️ Skipped (package not configured for coverage):" >> $GITHUB_STEP_SUMMARY
echo -e "$SKIPPED_FILES" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi
if [ -n "$UNCOVERED_FILES" ]; then
echo "#### ❌ Not Covered:" >> $GITHUB_STEP_SUMMARY
echo -e "$UNCOVERED_FILES" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Please add tests for the uncovered files before merging.**" >> $GITHUB_STEP_SUMMARY
echo "coverage_status=fail" >> $GITHUB_OUTPUT
else
echo "" >> $GITHUB_STEP_SUMMARY
echo "πŸŽ‰ **All changed files have adequate test coverage!**" >> $GITHUB_STEP_SUMMARY
echo "coverage_status=pass" >> $GITHUB_OUTPUT
fi
- name: Post coverage comment on PR
if: always()
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
// Check if this is a fork PR - forks don't have write permissions
const isFork = context.payload.pull_request?.head?.repo?.fork === true;
if (isFork) {
console.log('ℹ️ This PR is from a fork. Skipping PR comment (no write permissions).');
console.log('πŸ“Š Coverage results are available in the workflow summary above.');
return;
}
// Read the step summary
const summaryPath = process.env.GITHUB_STEP_SUMMARY;
let summary = '';
try {
summary = fs.readFileSync(summaryPath, 'utf8');
} catch (e) {
summary = 'πŸ“Š Coverage check completed. See workflow run for details.';
}
try {
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('πŸ“Š Coverage Report for Changed Files')
);
const commentBody = summary || 'πŸ“Š Coverage check completed. See workflow run for details.';
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: commentBody
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: commentBody
});
}
} catch (error) {
// Handle permission errors gracefully (e.g., for fork PRs)
if (error.status === 403) {
console.log('⚠️ Unable to post comment (permission denied). This is expected for fork PRs.');
console.log('πŸ“Š Coverage results are available in the workflow summary above.');
} else {
throw error;
}
}
- name: Fail if coverage is insufficient
if: steps.coverage-check.outputs.coverage_status == 'fail'
run: |
echo "❌ Some changed files lack test coverage. Please add tests before merging."
exit 1