build-package.yaml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. # This automation builds 3p packages based on a PR
  2. name: Build 3P Packages
  3. on:
  4. pull_request:
  5. branches:
  6. - main
  7. - development
  8. paths:
  9. - 'package_build_list_host_*.json'
  10. jobs:
  11. detect-changes:
  12. name: Detecting changes in PR to build
  13. runs-on: ubuntu-latest
  14. outputs:
  15. matrix: ${{ steps.detect-platform.outputs.matrix }}
  16. steps:
  17. - name: Checkout 3P source repo
  18. uses: actions/checkout@v4
  19. with:
  20. fetch-depth: 0
  21. - name: Get package and platform from JSON changes
  22. id: detect-platform
  23. run: |
  24. CHANGED_FILES=$(git diff ${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }} --name-only)
  25. # Construct the package and os into a json string to be consumed by Github Actions runners
  26. declare -A PACKAGES_JSON
  27. declare -A DOCKERFILE
  28. for FILE in $CHANGED_FILES; do
  29. if [[ $FILE == package_build_list_host_* ]]; then
  30. echo "Checking file $FILE"
  31. PLATFORM=$(echo $FILE | sed -n 's/package_build_list_host_\(.*\).json/\1/p')
  32. echo "Using platform $PLATFORM"
  33. # Only get the changes that can be built
  34. # First, get the diff output
  35. DIFF=$(git diff ${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }} \
  36. --no-ext-diff --unified=0 \
  37. --exit-code -a --no-prefix -- $FILE | egrep "^\+[^\+]" | egrep -v "^\+\+\+ ")
  38. # Use an associative array to track which packages we've already processed
  39. declare -A PROCESSED_PACKAGES
  40. # Then, iterate over the lines
  41. IFS=$'\n' # Process each line in the package build file
  42. for LINE in $DIFF; do
  43. unset IFS # Reset IFS to avoid word splitting
  44. PACKAGE=$(echo $LINE | cut -d'"' -f2)
  45. # Skip if we've already processed this package
  46. if [[ -n "${PROCESSED_PACKAGES[$PACKAGE]}" ]]; then
  47. continue
  48. fi
  49. PACKPATH=$(echo $LINE | grep -oE "package-system/[^/ ]+" | head -n 1)
  50. if [[ -z "${DOCKERFILE["$PACKAGE"]}" && -n "$PACKPATH" ]]; then
  51. DOCKER=$(test -e ${PACKPATH%% }/Dockerfile* && echo 1 || echo 0) # Assume the build scripts will use the Dockerfile if found in the package path
  52. DOCKERFILE["$PACKAGE"]=1 # Mark Dockerfile check as done
  53. fi
  54. # Determine the OS runner based on the package name
  55. if [[ $PACKAGE =~ "aarch64" ]]; then
  56. PACKAGE_OS="ubuntu-22.04-arm"
  57. echo "OS Image selected for $PACKAGE: $PACKAGE_OS"
  58. elif [[ $PACKAGE =~ "DirectXShaderCompilerDxc" ]] && [[ $PLATFORM =~ "windows" ]]; then
  59. PACKAGE_OS="windows-2019"
  60. echo "OS Image selected for $PACKAGE: $PACKAGE_OS"
  61. elif [[ $PLATFORM =~ "linux" ]]; then
  62. PACKAGE_OS="ubuntu-22.04"
  63. echo "OS Image selected for $PACKAGE: $PACKAGE_OS"
  64. elif [[ $PLATFORM =~ "windows" ]]; then
  65. PACKAGE_OS="windows-latest"
  66. echo "OS Image selected for $PACKAGE: $PACKAGE_OS"
  67. elif [[ $PLATFORM =~ "darwin" ]]; then
  68. PACKAGE_OS="macos-13"
  69. echo "OS Image selected for $PACKAGE: $PACKAGE_OS"
  70. else
  71. PACKAGE_OS="windows-latest" # Default
  72. echo "OS Image selected for $PACKAGE: $PACKAGE_OS (default)"
  73. fi
  74. PACKAGES_JSON["$PACKAGE"]="{\"package\": \"$PACKAGE\", \"os\": \"$PACKAGE_OS\", \"dockerfile\": \"$DOCKER\"}"
  75. # Mark as processed
  76. PROCESSED_PACKAGES[$PACKAGE]=1
  77. done
  78. unset IFS
  79. fi
  80. done
  81. # Construct the complete JSON from the array
  82. JSON="{\"include\":["
  83. for PKG_JSON in "${PACKAGES_JSON[@]}"; do
  84. JSON="$JSON$PKG_JSON,"
  85. done
  86. # Remove last "," and add closing brackets
  87. if [[ $JSON == *, ]]; then
  88. JSON="${JSON%?}"
  89. fi
  90. JSON="$JSON]}"
  91. echo $JSON
  92. # Set output
  93. echo "matrix=$( echo "$JSON" )" >> $GITHUB_OUTPUT
  94. validate-changes:
  95. name: Check changes for issues
  96. needs: detect-changes
  97. strategy:
  98. fail-fast: false
  99. matrix: ${{fromJson(needs.detect-changes.outputs.matrix)}}
  100. runs-on: ubuntu-latest
  101. steps:
  102. - name: Checkout 3P source repo
  103. uses: actions/checkout@v4
  104. - name: Check if package already exists in prod
  105. env:
  106. PROD_CDN: ${{ vars.PROD_CDN }} # Change this to compare on your own endpoint
  107. run: |
  108. url="${{ env.PROD_CDN }}/${{ matrix.package }}"
  109. if curl --head --silent --fail ${url}.tar.xz > /dev/null 2>&1; then
  110. echo ${{ matrix.package }} already exists in prod. Check the rev in the json file to ensure it is incremented
  111. exit 1
  112. else
  113. echo ${{ matrix.package }} does not exist in CDN, continuing...
  114. exit 0
  115. fi
  116. - name: Malware scan of repo
  117. uses: dell/common-github-actions/malware-scanner@main
  118. with:
  119. directories: .
  120. options: -r
  121. build-on-specific-os:
  122. name: Build on "${{ matrix.os }}" for "${{ matrix.package }}"
  123. needs: [detect-changes, validate-changes]
  124. strategy:
  125. fail-fast: false
  126. matrix: ${{fromJson(needs.detect-changes.outputs.matrix)}}
  127. runs-on: ${{ matrix.os }}
  128. steps:
  129. - name: Configure
  130. id: configure
  131. run: |
  132. git config --global core.longpaths true
  133. echo "uid_gid=$(id -u):$(id -g)" >> $GITHUB_OUTPUT
  134. - name: Expand disk size for Linux
  135. uses: easimon/maximize-build-space@v10
  136. if: runner.os == 'Linux' && !contains(matrix.os, 'arm')
  137. with:
  138. root-reserve-mb: 20000
  139. swap-size-mb: 200
  140. remove-dotnet: true
  141. remove-haskell: true
  142. remove-codeql: true
  143. - name: Checkout 3P source repo
  144. uses: actions/checkout@v4
  145. with:
  146. path: source
  147. fetch-depth: 0
  148. - name: Checkout 3P scripts repo
  149. uses: actions/checkout@v4
  150. with:
  151. repository: o3de/3p-package-scripts
  152. path: scripts
  153. - name: Update python
  154. uses: actions/setup-python@v4
  155. with:
  156. python-version: '3.10'
  157. cache: 'pip'
  158. - name: Install python dependancies
  159. run: |
  160. python3 -m pip install boto3 certifi
  161. - name: Update cmake/ninja
  162. uses: lukka/get-cmake@latest
  163. - name: Update msbuild path
  164. if: runner.os == 'Windows'
  165. uses: ilammy/[email protected]
  166. - name: Setup NDK
  167. env:
  168. ANDROID_NDK_VERSION: 25.1.8937393
  169. if: runner.os == 'Windows'
  170. run: |
  171. $sdkPath = if ($env:ANDROID_HOME) {
  172. $env:ANDROID_HOME
  173. } else {
  174. "$env:LOCALAPPDATA\Android\Sdk"
  175. }
  176. # Remove versioned NDK directories
  177. if (Test-Path "$sdkPath\ndk") {
  178. Get-ChildItem "$sdkPath\ndk" -Directory |
  179. Where-Object { $_.Name -match '^\d' } |
  180. ForEach-Object {
  181. Remove-Item $_.FullName -Recurse -Force
  182. Write-Host "Removed NDK version: $($_.Name)" -ForegroundColor Green
  183. }
  184. }
  185. # Install NDK version based on ANDROID_NDK_VERSION
  186. if ($env:ANDROID_NDK_VERSION) {
  187. $sdkmanager = "$sdkPath\cmdline-tools\latest\bin\sdkmanager.bat"
  188. if (-not (Test-Path $sdkmanager)) {
  189. $sdkmanager = "$sdkPath\tools\bin\sdkmanager.bat"
  190. }
  191. if (Test-Path $sdkmanager) {
  192. Write-Host "Installing NDK version $env:ANDROID_NDK_VERSION..." -ForegroundColor Yellow
  193. & $sdkmanager --install "ndk;$env:ANDROID_NDK_VERSION" --channel=0
  194. } else {
  195. Write-Host "sdkmanager not found. Cannot install NDK." -ForegroundColor Red
  196. exit 1
  197. }
  198. }
  199. # Set NDK folder path in the env vars
  200. $ndkRoot = "$sdkPath\ndk\$env:ANDROID_NDK_VERSION"
  201. echo ANDROID_NDK=$ndkRoot >> $env:GITHUB_ENV
  202. echo ANDROID_NDK_HOME=$ndkRoot >> $env:GITHUB_ENV
  203. echo ANDROID_NDK_ROOT=$ndkRoot >> $env:GITHUB_ENV
  204. - name: Install clang/gcc
  205. if: runner.os == 'Linux'
  206. env:
  207. CLANG_VER: 12
  208. GCC_VER: 9
  209. run: |
  210. sudo apt-get install -y clang-${{ env.CLANG_VER }} gcc-${{ env.GCC_VER }} g++-${{ env.GCC_VER }}
  211. sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${{ env.CLANG_VER }} 10
  212. sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${{ env.CLANG_VER }} 10
  213. sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${{ env.GCC_VER }} 10
  214. sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${{ env.GCC_VER }} 10
  215. - name: Use sccache
  216. uses: hendrikmuhs/[email protected]
  217. if: ${{ !contains(matrix.os, 'arm') }}
  218. with:
  219. variant: sccache
  220. max-size: 2048M
  221. key: ${{ matrix.package }}-${{ matrix.os }}
  222. restore-keys:
  223. ${{ matrix.package }}-${{ matrix.os }}
  224. - name: Run build command
  225. env:
  226. CMAKE_CXX_COMPILER_LAUNCHER: sccache
  227. CMAKE_C_COMPILER_LAUNCHER: sccache
  228. CMAKE_GENERATOR: Ninja # ccache/sccache cannot be used as the compiler launcher under cmake if the generator is MSBuild
  229. run: |
  230. python3 scripts/o3de_package_scripts/build_package.py --search_path source ${{ matrix.package }}
  231. - name: Upload packages
  232. uses: actions/upload-artifact@v4
  233. with:
  234. name: ${{ matrix.package }}
  235. path: source/packages/*
  236. validate-packages:
  237. name: Validating ${{ matrix.package }}
  238. needs: [detect-changes, build-on-specific-os]
  239. runs-on: 'ubuntu-latest'
  240. strategy:
  241. fail-fast: false
  242. matrix: ${{fromJson(needs.detect-changes.outputs.matrix)}}
  243. steps:
  244. - name: Download packages
  245. uses: actions/download-artifact@v4
  246. with:
  247. name: ${{ matrix.package }}
  248. - name: Verify SHA256
  249. run: |
  250. echo "$(cat ${{ matrix.package }}.tar.xz.SHA256SUMS)"
  251. echo "$(cat ${{ matrix.package }}.tar.xz.SHA256SUMS | cut -d" " -f1) ${{ matrix.package }}.tar.xz" | sha256sum --check
  252. - name: Decompress package
  253. if: ${{ !contains(matrix.package, 'aarch64') }}
  254. run: |
  255. tar -xvf ${{ matrix.package }}.tar.xz
  256. - name: Malware scan
  257. uses: dell/common-github-actions/malware-scanner@main
  258. with:
  259. directories: .
  260. options: -r