build-samples.yml 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. name: Build Samples
  2. on:
  3. workflow_dispatch:
  4. push:
  5. branches: [ main, develop ]
  6. pull_request:
  7. branches: [ main, develop ]
  8. schedule:
  9. - cron: "0 3 * * 1" # Weekly (Mon) build to keep artifacts fresh
  10. permissions:
  11. contents: read
  12. env:
  13. DOTNET_NOLOGO: true
  14. CONFIGURATION: Release
  15. jobs:
  16. discover:
  17. runs-on: macos-latest
  18. outputs:
  19. projects: ${{ steps.collect.outputs.projects }}
  20. skipped: ${{ steps.collect.outputs.skipped }}
  21. steps:
  22. - name: Checkout
  23. uses: actions/checkout@v4
  24. - name: Collect & filter Desktop platform project files
  25. id: collect
  26. shell: bash
  27. run: |
  28. set -e
  29. # Ensure jq is available (macOS image usually has it, fallback to brew)
  30. if ! command -v jq >/dev/null 2>&1; then
  31. echo "jq not found, installing via Homebrew";
  32. brew update >/dev/null 2>&1 || true
  33. brew install jq >/dev/null 2>&1
  34. fi
  35. # Find all Desktop platform csproj files: **/Platforms/Desktop/*.csproj (portable without mapfile)
  36. desktop_projects_tmp=$(mktemp)
  37. find . -type f -path '*/Platforms/Desktop/*.csproj' | sort > "$desktop_projects_tmp"
  38. if [ ! -s "$desktop_projects_tmp" ]; then
  39. echo "No Desktop platform projects found."
  40. echo "projects=[]" >> "$GITHUB_OUTPUT"
  41. echo "skipped=[]" >> "$GITHUB_OUTPUT"
  42. exit 0
  43. fi
  44. echo "Testing restore for discovered Desktop projects:"
  45. success_tmp=$(mktemp)
  46. skipped_tmp=$(mktemp)
  47. while IFS= read -r proj; do
  48. echo "Attempting restore: $proj"
  49. if dotnet restore "$proj" >/dev/null 2>&1; then
  50. echo " OK $proj"
  51. echo "$proj" >> "$success_tmp"
  52. else
  53. echo " SKIP (restore failed) $proj"
  54. echo "$proj" >> "$skipped_tmp"
  55. fi
  56. done < "$desktop_projects_tmp"
  57. if [ ! -s "$success_tmp" ]; then
  58. echo "No projects restored successfully.";
  59. echo "projects=[]" >> "$GITHUB_OUTPUT"
  60. else
  61. json=$(jq -R . < "$success_tmp" | jq -s -c .)
  62. echo "projects=$json" >> "$GITHUB_OUTPUT"
  63. fi
  64. if [ -s "$skipped_tmp" ]; then
  65. skipped_json=$(jq -R . < "$skipped_tmp" | jq -s -c .)
  66. echo "skipped=$skipped_json" >> "$GITHUB_OUTPUT"
  67. else
  68. echo "skipped=[]" >> "$GITHUB_OUTPUT"
  69. fi
  70. echo "Restore filtering complete.";
  71. echo "Successful projects:"; cat "$success_tmp" || true
  72. echo "Skipped projects:"; cat "$skipped_tmp" || true
  73. rm -f "$desktop_projects_tmp" "$success_tmp" "$skipped_tmp"
  74. build-desktop-bundles:
  75. needs: discover
  76. if: ${{ needs.discover.outputs.projects != '[]' && needs.discover.outputs.projects != '' }}
  77. runs-on: macos-latest
  78. env:
  79. MGFXC_WINE_PATH: /Users/runner/.winemonogame
  80. DYLD_LIBRARY_PATH: /usr/lib:/usr/local/lib:/opt/homebrew/lib:/usr/local/bin
  81. strategy:
  82. fail-fast: false
  83. matrix:
  84. project: ${{ fromJson(needs.discover.outputs.projects) }}
  85. steps:
  86. - name: Checkout
  87. uses: actions/checkout@v4
  88. - name: Setup .NET 8
  89. uses: actions/setup-dotnet@v4
  90. with:
  91. dotnet-version: |
  92. 8.0.x
  93. - name: Setup for MonoGame
  94. uses: infinitespace-studios/monogame-actions/[email protected]
  95. - name: Install MonoPack
  96. run: dotnet tool install --global MonoPack
  97. - name: Build and Package Desktop Bundle
  98. id: package
  99. continue-on-error: true
  100. shell: bash
  101. run: |
  102. set -e
  103. PROJ="${{ matrix.project }}"
  104. NAME=$(basename "$PROJ" .csproj)
  105. PROJ_DIR=$(dirname "$PROJ")
  106. ARTIFACTS_DIR="./artifacts/$NAME"
  107. echo "Project path: $PROJ"
  108. echo "Project name: $NAME"
  109. echo "Project directory: $PROJ_DIR"
  110. echo "Output directory: $ARTIFACTS_DIR"
  111. # Check for macOS assets
  112. INFO_PLIST="$PROJ_DIR/Info.plist"
  113. ICNS_FILE="$PROJ_DIR/${NAME}.icns"
  114. if [ ! -f "$INFO_PLIST" ]; then
  115. echo "Error: Info.plist not found at $INFO_PLIST"
  116. echo "Please run ./generate-macos-assets.sh to generate macOS assets"
  117. exit 1
  118. fi
  119. echo "Packaging $NAME for all desktop platforms"
  120. if [ -f "$ICNS_FILE" ]; then
  121. echo "Using icon file: $ICNS_FILE"
  122. monopack -p "$PROJ" \
  123. -o "$ARTIFACTS_DIR" \
  124. -rids win-x64,linux-x64,osx-x64,osx-arm64 \
  125. -i "$INFO_PLIST" \
  126. -c "$ICNS_FILE" \
  127. -v \
  128. --macos-universal
  129. else
  130. echo "No .icns file found, packaging without custom icon"
  131. monopack -p "$PROJ" \
  132. -o "$ARTIFACTS_DIR" \
  133. -rids win-x64,linux-x64,osx-x64,osx-arm64 \
  134. -i "$INFO_PLIST" \
  135. -v \
  136. --macos-universal
  137. fi
  138. echo "Generated artifacts:"
  139. find "$ARTIFACTS_DIR" -type f -name "*.zip" || echo "No zip files found"
  140. ls -la "$ARTIFACTS_DIR" || echo "Artifacts directory not found"
  141. echo "name=$NAME" >> "$GITHUB_OUTPUT"
  142. - name: Record Build Result
  143. if: always()
  144. shell: bash
  145. run: |
  146. PROJ="${{ matrix.project }}"
  147. NAME=$(basename "$PROJ" .csproj)
  148. RESULT_DIR="./build-results"
  149. mkdir -p "$RESULT_DIR"
  150. if [ "${{ steps.package.outcome }}" = "success" ]; then
  151. jq -n --arg project "$NAME" --arg status "success" --arg error "" \
  152. '{project: $project, status: $status, error: $error}' > "$RESULT_DIR/$NAME.json"
  153. else
  154. # Capture the error - this is a simplified version, actual error would be in logs
  155. jq -n --arg project "$NAME" --arg status "failure" --arg error "Build or packaging failed - see job logs for details" \
  156. '{project: $project, status: $status, error: $error}' > "$RESULT_DIR/$NAME.json"
  157. fi
  158. - name: Upload Build Result
  159. if: always()
  160. uses: actions/upload-artifact@v4
  161. with:
  162. name: build-result-${{ steps.package.outputs.name }}
  163. path: build-results/*.json
  164. retention-days: 1
  165. - name: Upload Windows Bundle
  166. if: steps.package.outcome == 'success'
  167. uses: actions/upload-artifact@v4
  168. with:
  169. name: ${{ steps.package.outputs.name }}-Windows
  170. path: artifacts/${{ steps.package.outputs.name }}/*-win-x64.zip
  171. if-no-files-found: error
  172. retention-days: 14
  173. - name: Upload Linux Bundle
  174. if: steps.package.outcome == 'success'
  175. uses: actions/upload-artifact@v4
  176. with:
  177. name: ${{ steps.package.outputs.name }}-Linux
  178. path: artifacts/${{ steps.package.outputs.name }}/*-linux-x64.tar.gz
  179. if-no-files-found: error
  180. retention-days: 14
  181. - name: Upload macOS App Bundle
  182. if: steps.package.outcome == 'success'
  183. uses: actions/upload-artifact@v4
  184. with:
  185. name: ${{ steps.package.outputs.name }}-macOS-Universal
  186. path: artifacts/${{ steps.package.outputs.name }}/*-universal.tar.gz
  187. if-no-files-found: error
  188. retention-days: 14
  189. summary:
  190. needs: [discover, build-desktop-bundles]
  191. if: always()
  192. runs-on: macos-latest
  193. steps:
  194. - name: Download Build Results
  195. if: needs.discover.outputs.projects != '[]' && needs.discover.outputs.projects != ''
  196. uses: actions/download-artifact@v4
  197. with:
  198. pattern: build-result-*
  199. path: build-results
  200. merge-multiple: true
  201. - name: Build Summary
  202. shell: bash
  203. run: |
  204. echo "# Desktop Sample Build Summary" >> $GITHUB_STEP_SUMMARY
  205. echo "" >> $GITHUB_STEP_SUMMARY
  206. # Process build results if they exist
  207. if [ -d "build-results" ] && [ "$(ls -A build-results 2>/dev/null)" ]; then
  208. echo "## Build Results" >> $GITHUB_STEP_SUMMARY
  209. echo "" >> $GITHUB_STEP_SUMMARY
  210. echo "| Project | Status | Error |" >> $GITHUB_STEP_SUMMARY
  211. echo "|---------|--------|-------|" >> $GITHUB_STEP_SUMMARY
  212. success_count=0
  213. failure_count=0
  214. for result_file in build-results/*.json; do
  215. if [ -f "$result_file" ]; then
  216. project=$(jq -r '.project' "$result_file")
  217. status=$(jq -r '.status' "$result_file")
  218. error=$(jq -r '.error' "$result_file")
  219. if [ "$status" = "success" ]; then
  220. echo "| $project | ✅ Success | - |" >> $GITHUB_STEP_SUMMARY
  221. success_count=$((success_count + 1))
  222. else
  223. echo "| $project | ❌ Failed | $error |" >> $GITHUB_STEP_SUMMARY
  224. failure_count=$((failure_count + 1))
  225. fi
  226. fi
  227. done
  228. echo "" >> $GITHUB_STEP_SUMMARY
  229. echo "**Summary:** $success_count succeeded, $failure_count failed" >> $GITHUB_STEP_SUMMARY
  230. echo "" >> $GITHUB_STEP_SUMMARY
  231. elif [ "${{ needs.discover.outputs.projects }}" = "[]" ] || [ -z "${{ needs.discover.outputs.projects }}" ]; then
  232. echo "No Desktop platform projects were built (no successful restores)." >> $GITHUB_STEP_SUMMARY
  233. echo "" >> $GITHUB_STEP_SUMMARY
  234. fi
  235. # Show skipped projects
  236. if [ -n "${{ needs.discover.outputs.skipped }}" ] && [ "${{ needs.discover.outputs.skipped }}" != "[]" ]; then
  237. echo "## Skipped Projects (Restore Failed)" >> $GITHUB_STEP_SUMMARY
  238. echo "" >> $GITHUB_STEP_SUMMARY
  239. echo "${{ needs.discover.outputs.skipped }}" | jq -r '.[]' | while read -r proj; do
  240. name=$(basename "$proj" .csproj)
  241. echo "- ⏭️ $name" >> $GITHUB_STEP_SUMMARY
  242. done
  243. echo "" >> $GITHUB_STEP_SUMMARY
  244. fi
  245. echo "---" >> $GITHUB_STEP_SUMMARY
  246. echo "Cross-platform bundles (Windows, Linux, macOS) are available as separate artifacts for successful builds." >> $GITHUB_STEP_SUMMARY