Merge pull request #78 from bvdcode/feature/examples-constructs-bvdcode #38
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: Build All Projects | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| workflow_dispatch: # Allow manual triggering | |
| schedule: | |
| # Check for new Ivy versions daily at 6 AM UTC | |
| - cron: '0 6 * * *' | |
| env: | |
| DOTNET_VERSION: '9.0.x' | |
| DOTNET_NOLOGO: true | |
| DOTNET_CLI_TELEMETRY_OPTOUT: true | |
| jobs: | |
| check-ivy-version: | |
| name: Check Ivy Version | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should-build: ${{ steps.version-check.outputs.should-build }} | |
| current-version: ${{ steps.version-check.outputs.current-version }} | |
| latest-version: ${{ steps.version-check.outputs.latest-version }} | |
| version-changed: ${{ steps.version-check.outputs.version-changed }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Check Ivy version | |
| id: version-check | |
| run: | | |
| # Get the latest Ivy version from NuGet | |
| echo "🔍 Checking latest Ivy version on NuGet..." | |
| latest_version=$(curl -s "https://api.nuget.org/v3-flatcontainer/ivy/index.json" | jq -r '.versions | last') | |
| echo "Latest Ivy version: $latest_version" | |
| # Since all projects use wildcards (1.*), we'll determine the resolved version later | |
| current_version="wildcard" | |
| version_changed="false" | |
| should_build="false" | |
| # For scheduled runs, check if there's a new version since last run | |
| if [ "${{ github.event_name }}" == "schedule" ]; then | |
| echo "📅 Scheduled run - checking for Ivy version updates..." | |
| # Try to get the last known version from a previous run | |
| # We'll use GitHub's cache or artifact system to store this | |
| last_known_version_file=".github/last-ivy-version.txt" | |
| last_known_version="" | |
| if [ -f "$last_known_version_file" ]; then | |
| last_known_version=$(cat "$last_known_version_file") | |
| echo "Last known Ivy version: $last_known_version" | |
| else | |
| echo "No previous version record found - will build to establish baseline" | |
| last_known_version="" | |
| fi | |
| # Compare versions | |
| if [ -z "$last_known_version" ] || [ "$last_known_version" != "$latest_version" ]; then | |
| echo "🆕 New Ivy version detected! ($last_known_version → $latest_version)" | |
| should_build="true" | |
| version_changed="true" | |
| # Store the new version for next time | |
| echo "$latest_version" > "$last_known_version_file" | |
| else | |
| echo "✅ No new Ivy version since last check" | |
| should_build="false" | |
| version_changed="false" | |
| fi | |
| fi | |
| # For push/PR/manual events, always build regardless of version | |
| if [ "${{ github.event_name }}" == "push" ] || [ "${{ github.event_name }}" == "pull_request" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ]; then | |
| should_build="true" | |
| echo "🔄 Code change detected - will build" | |
| # Also update the version file for manual/push events to keep it current | |
| echo "$latest_version" > ".github/last-ivy-version.txt" | |
| fi | |
| echo "should-build=$should_build" >> $GITHUB_OUTPUT | |
| echo "current-version=$current_version" >> $GITHUB_OUTPUT | |
| echo "latest-version=$latest_version" >> $GITHUB_OUTPUT | |
| echo "version-changed=$version_changed" >> $GITHUB_OUTPUT | |
| - name: Commit version tracking file | |
| if: steps.version-check.outputs.version-changed == 'true' || github.event_name != 'schedule' | |
| run: | | |
| # Configure git | |
| git config --local user.email "action@github.com" | |
| git config --local user.name "GitHub Action" | |
| # Check if there are changes to commit | |
| if [ -f ".github/last-ivy-version.txt" ]; then | |
| git add .github/last-ivy-version.txt | |
| # Only commit if there are actual changes | |
| if ! git diff --staged --quiet; then | |
| git commit -m "Update last known Ivy version to ${{ steps.version-check.outputs.latest-version }}" | |
| git push | |
| echo "✅ Updated version tracking file" | |
| else | |
| echo "ℹ️ No changes to version tracking file" | |
| fi | |
| fi | |
| discover-projects: | |
| name: Discover Projects | |
| runs-on: ubuntu-latest | |
| needs: check-ivy-version | |
| if: needs.check-ivy-version.outputs.should-build == 'true' | |
| outputs: | |
| projects: ${{ steps.find-projects.outputs.projects }} | |
| project-count: ${{ steps.find-projects.outputs.project-count }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Find all .NET projects | |
| id: find-projects | |
| run: | | |
| # Find all .csproj files, excluding those in bin/obj directories | |
| projects=$(find . -name "*.csproj" -not -path "*/bin/*" -not -path "*/obj/*" | sort) | |
| # Convert to JSON array for matrix strategy | |
| project_array="[" | |
| first=true | |
| while IFS= read -r project; do | |
| if [ "$first" = true ]; then | |
| first=false | |
| else | |
| project_array="$project_array," | |
| fi | |
| # Get project directory name for display | |
| dir_name=$(dirname "$project" | xargs basename) | |
| project_array="$project_array{\"path\":\"$project\",\"name\":\"$dir_name\"}" | |
| done <<< "$projects" | |
| project_array="$project_array]" | |
| # Count projects | |
| project_count=$(echo "$projects" | wc -l) | |
| echo "Found $project_count projects:" | |
| echo "$projects" | |
| echo "projects=$project_array" >> $GITHUB_OUTPUT | |
| echo "project-count=$project_count" >> $GITHUB_OUTPUT | |
| build-projects: | |
| name: Build | |
| runs-on: ubuntu-latest | |
| needs: [check-ivy-version, discover-projects] | |
| if: needs.check-ivy-version.outputs.should-build == 'true' && needs.discover-projects.outputs.project-count > 0 | |
| strategy: | |
| fail-fast: false # Continue building other projects even if one fails | |
| matrix: | |
| project: ${{ fromJson(needs.discover-projects.outputs.projects) }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Display .NET info | |
| run: dotnet --info | |
| - name: Cache NuGet packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore dependencies | |
| run: dotnet restore "${{ matrix.project.path }}" | |
| - name: Build project | |
| run: | | |
| echo "🔨 Building: ${{ matrix.project.name }}" | |
| dotnet build "${{ matrix.project.path }}" \ | |
| --configuration Release \ | |
| --no-restore \ | |
| --verbosity normal | |
| - name: Upload build artifacts (on failure) | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: build-logs-${{ matrix.project.name }} | |
| path: | | |
| **/bin/**/*.log | |
| **/obj/**/*.log | |
| retention-days: 7 | |
| detect-resolved-version: | |
| name: Detect Resolved Ivy Version | |
| runs-on: ubuntu-latest | |
| needs: [check-ivy-version, build-projects] | |
| if: needs.check-ivy-version.outputs.should-build == 'true' && (success() || failure()) | |
| outputs: | |
| resolved-version: ${{ steps.get-version.outputs.resolved-version }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Get resolved Ivy version | |
| id: get-version | |
| run: | | |
| echo "🔍 Determining resolved Ivy version from packages..." | |
| # Find a project to check resolved version | |
| project_file=$(find . -name "*.csproj" -not -path "*/bin/*" -not -path "*/obj/*" | head -1) | |
| if [ -n "$project_file" ]; then | |
| echo "Checking resolved packages for: $project_file" | |
| # Restore packages to get lock file | |
| dotnet restore "$project_file" --verbosity quiet | |
| # Get the resolved version from the project assets | |
| project_dir=$(dirname "$project_file") | |
| assets_file="$project_dir/obj/project.assets.json" | |
| if [ -f "$assets_file" ]; then | |
| # Extract Ivy version from project.assets.json | |
| resolved_version=$(jq -r '.libraries | to_entries[] | select(.key | startswith("Ivy/")) | .key | split("/")[1]' "$assets_file" 2>/dev/null | head -1) | |
| if [ -n "$resolved_version" ] && [ "$resolved_version" != "null" ]; then | |
| echo "✅ Resolved Ivy version: $resolved_version" | |
| echo "resolved-version=$resolved_version" >> $GITHUB_OUTPUT | |
| else | |
| echo "⚠️ Could not determine resolved version from assets file" | |
| echo "resolved-version=${{ needs.check-ivy-version.outputs.latest-version }}" >> $GITHUB_OUTPUT | |
| fi | |
| else | |
| echo "⚠️ Project assets file not found, using latest version" | |
| echo "resolved-version=${{ needs.check-ivy-version.outputs.latest-version }}" >> $GITHUB_OUTPUT | |
| fi | |
| else | |
| echo "⚠️ No project files found" | |
| echo "resolved-version=unknown" >> $GITHUB_OUTPUT | |
| fi | |
| build-summary: | |
| name: Build Summary | |
| runs-on: ubuntu-latest | |
| needs: [check-ivy-version, discover-projects, build-projects, detect-resolved-version] | |
| if: always() && needs.check-ivy-version.outputs.should-build == 'true' # Run even if some builds failed | |
| steps: | |
| - name: Generate build summary | |
| run: | | |
| echo "# 🚀 Ivy-Examples Build Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| # Add Ivy version information | |
| echo "## 📦 Ivy Version Information" >> $GITHUB_STEP_SUMMARY | |
| resolved_version="${{ needs.detect-resolved-version.outputs.resolved-version }}" | |
| latest_version="${{ needs.check-ivy-version.outputs.latest-version }}" | |
| echo "- **Project Configuration:** \`1.*\` (wildcard)" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Resolved Version:** $resolved_version" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Latest Available:** $latest_version" >> $GITHUB_STEP_SUMMARY | |
| if [ "$resolved_version" = "$latest_version" ]; then | |
| echo "- **Status:** ✅ Using latest version" >> $GITHUB_STEP_SUMMARY | |
| elif [ "${{ needs.check-ivy-version.outputs.version-changed }}" == "true" ]; then | |
| echo "- **Status:** 🆕 New version available!" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "- **Status:** ℹ️ Resolved to compatible version" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Total Projects:** ${{ needs.discover-projects.outputs.project-count }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| # Check build results | |
| if [ "${{ needs.build-projects.result }}" == "success" ]; then | |
| echo "## ✅ All builds successful! 🎉" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "All ${{ needs.discover-projects.outputs.project-count }} projects built successfully." >> $GITHUB_STEP_SUMMARY | |
| elif [ "${{ needs.build-projects.result }}" == "failure" ]; then | |
| echo "## ❌ Some builds failed" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "One or more projects failed to build. Check the individual job logs for details." >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "## ⚠️ Build status: ${{ needs.build-projects.result }}" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "## 📊 Build Matrix Results" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Check individual job results in the workflow run above." >> $GITHUB_STEP_SUMMARY | |
| - name: Set workflow status | |
| run: | | |
| if [ "${{ needs.build-projects.result }}" != "success" ]; then | |
| echo "❌ Build workflow failed" | |
| exit 1 | |
| else | |
| echo "✅ Build workflow succeeded" | |
| fi | |
| # Optional: Create a simple build status badge | |
| create-badge: | |
| name: Update Build Badge | |
| runs-on: ubuntu-latest | |
| needs: [check-ivy-version, build-summary, detect-resolved-version] | |
| if: github.ref == 'refs/heads/main' && always() && needs.check-ivy-version.outputs.should-build == 'true' | |
| steps: | |
| - name: Create build status badge | |
| run: | | |
| if [ "${{ needs.build-summary.result }}" == "success" ]; then | |
| badge_color="brightgreen" | |
| badge_message="passing" | |
| else | |
| badge_color="red" | |
| badge_message="failing" | |
| fi | |
| echo "Build status: $badge_message ($badge_color)" | |
| # You can extend this to actually update a badge service like shields.io |