Skip to content

feat: add cross-platform GUI desktop app (Avalonia) with drag-drop, b… #193

feat: add cross-platform GUI desktop app (Avalonia) with drag-drop, b…

feat: add cross-platform GUI desktop app (Avalonia) with drag-drop, b… #193

Workflow file for this run

name: CI
on:
push:
branches: [ main, master ]
paths-ignore:
- '**.md'
- 'documents/**'
- 'dotnet_ai_azure_book/**'
- 'book/**'
- 'MiniPdf.wiki/**'
- 'LICENSE'
pull_request:
branches: [ main, master ]
paths-ignore:
- '**.md'
- 'documents/**'
- 'dotnet_ai_azure_book/**'
- 'book/**'
- 'MiniPdf.wiki/**'
- 'LICENSE'
permissions:
contents: read
pull-requests: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore --configuration Release
- name: Test
run: dotnet test --no-build --configuration Release --verbosity normal --logger "trx;LogFileName=test-results.trx"
- name: Pack (verify NuGet package)
run: dotnet pack src/MiniPdf/MiniPdf.csproj --no-build --configuration Release --output ./nupkg
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: '**/test-results.trx'
ai-security-scan:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
needs: build
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get PR diff
id: diff
run: |
DIFF=$(git diff origin/${{ github.base_ref }}...HEAD -- '*.cs' '*.csproj' || true)
if [ -z "$DIFF" ]; then
echo "No code changes detected."
echo "skip=true" >> $GITHUB_OUTPUT
else
# Save diff to file to avoid shell escaping issues
echo "$DIFF" > /tmp/pr_diff.txt
echo "skip=false" >> $GITHUB_OUTPUT
fi
- name: AI Security Review
if: steps.diff.outputs.skip != 'true'
env:
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }}
AZURE_OPENAI_DEPLOYMENT: ${{ secrets.AZURE_OPENAI_DEPLOYMENT }}
run: |
DIFF=$(cat /tmp/pr_diff.txt)
# Truncate diff if too large (max ~12000 chars to fit in context)
if [ ${#DIFF} -gt 12000 ]; then
DIFF="${DIFF:0:12000}... [truncated]"
fi
INSTRUCTIONS=$(cat .github/copilot-code-review.md 2>/dev/null || echo "Review for security issues.")
API_VERSION="2025-01-01-preview"
URL="${AZURE_OPENAI_ENDPOINT%/}/openai/deployments/${AZURE_OPENAI_DEPLOYMENT}/chat/completions?api-version=${API_VERSION}"
# Build JSON payload safely using jq
PAYLOAD=$(jq -n \
--arg instructions "$INSTRUCTIONS" \
--arg diff "$DIFF" \
'{
messages: [
{ role: "system", content: $instructions },
{ role: "user", content: ("Review this code diff for security vulnerabilities in APPLICATION SOURCE CODE ONLY. Respond ONLY with a JSON object (no markdown, no code blocks): {\"passed\": true/false, \"issues\": [\"description1\", \"description2\"]}. Set passed=true if no security issues found in application code, passed=false only for real security concerns like SQL injection, XSS, path traversal, hardcoded credentials in source code, etc. Do NOT flag CI/CD workflow configuration or documentation changes as issues.\n\nDiff:\n" + $diff) }
],
temperature: 0.1
}')
RESPONSE=$(curl -s "$URL" \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d "$PAYLOAD")
# Extract content
CONTENT=$(echo "$RESPONSE" | jq -r '.choices[0].message.content // empty')
if [ -z "$CONTENT" ]; then
echo "::error::Failed to get AI review response"
echo "$RESPONSE" | jq .
exit 1
fi
echo "=== AI Security Review Result ==="
echo "$CONTENT"
echo "================================="
# Parse JSON from response: strip markdown code blocks, then parse with jq
CLEAN_CONTENT=$(echo "$CONTENT" | sed '/^```/d')
# Use 'if .passed then "true" else "false" end' to handle boolean false correctly
PASSED=$(echo "$CLEAN_CONTENT" | jq -r 'if .passed == true then "true" elif .passed == false then "false" else "unknown" end' 2>/dev/null)
if [ "$PASSED" = "false" ]; then
echo ""
echo "::error::AI Security Review FAILED - security issues detected"
echo "$CLEAN_CONTENT" | jq -r '.issues[]?' 2>/dev/null | while read -r issue; do
echo "::warning::$issue"
done
exit 1
elif [ "$PASSED" = "true" ]; then
echo ""
echo "✅ AI Security Review PASSED - no security issues found"
else
echo "::warning::Could not parse AI review result, treating as FAIL for safety"
exit 1
fi
- name: Skip notice
if: steps.diff.outputs.skip == 'true'
run: echo "✅ No code changes to review"