|
| 1 | +name: Build Nabla Workflow |
| 2 | + |
| 3 | +on: |
| 4 | + push: |
| 5 | + pull_request: |
| 6 | + workflow_dispatch: |
| 7 | + |
| 8 | +permissions: |
| 9 | + contents: read |
| 10 | + |
| 11 | +concurrency: |
| 12 | + group: push-lock-${{ github.ref }} |
| 13 | + cancel-in-progress: true |
| 14 | + |
| 15 | +jobs: |
| 16 | + build-windows: |
| 17 | + runs-on: windows-2022 |
| 18 | + |
| 19 | + env: |
| 20 | + image: ghcr.io/devsh-graphics-programming/docker-nanoserver-msvc-winsdk |
| 21 | + entry: pwsh.exe |
| 22 | + cmd: -NoLogo -NoProfile -ExecutionPolicy Bypass |
| 23 | + mount: C:\mount\nabla |
| 24 | + binary: C:\mount\nabla\build-ct |
| 25 | + install: build-ct\install |
| 26 | + |
| 27 | + strategy: |
| 28 | + fail-fast: false |
| 29 | + matrix: |
| 30 | + # vendor: [msvc, clangcl] |
| 31 | + # TODO: Yas please fix ClangCL, we have a few new compile errors |
| 32 | + # if we build MSVC then build "run-compiler-explorer" target, for ClangCL build just "nsc" |
| 33 | + vendor: [msvc] |
| 34 | + config: [Release, Debug, RelWithDebInfo] |
| 35 | + tag: ['17.13.6'] |
| 36 | + |
| 37 | + steps: |
| 38 | + - name: Environment Setup |
| 39 | + run: | |
| 40 | + Add-MpPreference -ExclusionPath "${{ github.workspace }}" |
| 41 | + Add-MpPreference -ExclusionExtension "*.*" |
| 42 | + Add-MpPreference -ExclusionProcess "docker.exe" |
| 43 | + Add-MpPreference -ExclusionProcess "dockerd.exe" |
| 44 | + Set-MpPreference -RemediationScheduleDay 8 |
| 45 | + Set-MpPreference -DisableRealtimeMonitoring $true |
| 46 | + Set-MpPreference -DisableRemovableDriveScanning $true |
| 47 | + Set-MpPreference -DisableArchiveScanning $true |
| 48 | + Set-MpPreference -DisableScanningMappedNetworkDrivesForFullScan $true |
| 49 | +
|
| 50 | + if (-not (docker network ls --format '{{.Name}}' | Where-Object { $_ -eq 'docker_default' })) { |
| 51 | + docker network create --driver nat docker_default |
| 52 | + if ($LASTEXITCODE -ne 0) { exit 1 } |
| 53 | + } |
| 54 | +
|
| 55 | + - name: Set prefix |
| 56 | + id: set-prefix |
| 57 | + shell: pwsh |
| 58 | + run: | |
| 59 | + $prefix = "run-windows-${{ matrix.tag }}-${{ matrix.vendor }}-${{ matrix.config }}" |
| 60 | + $owner = "${{ github.repository_owner }}" |
| 61 | + $package = "nabla-shader-compiler-godbolt" |
| 62 | + $tag = "build-${{ matrix.vendor }}-${{ matrix.config }}-${{ matrix.tag }}" |
| 63 | + $nscTargetTaggedImage = "ghcr.io/${owner}/${package}:${tag}".ToLower() |
| 64 | + $nscTargetTaggedImageLatest = "ghcr.io/${owner}/${package}:latest".ToLower() |
| 65 | +
|
| 66 | + $shouldPushImage = ( |
| 67 | + "${{ github.ref }}" -eq "refs/heads/master" -and |
| 68 | + "${{ matrix.vendor }}" -eq "msvc" -and |
| 69 | + "${{ matrix.config }}" -eq "Release" |
| 70 | + ) |
| 71 | +
|
| 72 | + Write-Host "::notice::Should push image? $shouldPushImage" |
| 73 | + |
| 74 | + "prefix=$prefix" >> $env:GITHUB_OUTPUT |
| 75 | + "nscTargetTaggedImage=$nscTargetTaggedImage" >> $env:GITHUB_OUTPUT |
| 76 | + "nscTargetTaggedImageLatest=$nscTargetTaggedImageLatest" >> $env:GITHUB_OUTPUT |
| 77 | + "shouldPushImage=$shouldPushImage" >> $env:GITHUB_OUTPUT |
| 78 | +
|
| 79 | + - name: Checkout |
| 80 | + uses: actions/checkout@v4 |
| 81 | + with: |
| 82 | + submodules: 'recursive' |
| 83 | + |
| 84 | + - name: Pull Image |
| 85 | + run: | |
| 86 | + docker pull "${{ env.image }}:${{ matrix.tag }}" |
| 87 | +
|
| 88 | + - name: Run Container |
| 89 | + run: | |
| 90 | + $ctx = docker context show |
| 91 | + $dockerHost = (docker context inspect $ctx | ConvertFrom-Json).Endpoints.docker.Host |
| 92 | + $pipeName = [regex]::Match($dockerHost, '/pipe/(?<n>.+)$').Groups['n'].Value |
| 93 | + $pipeHost = "\\.\pipe\$pipeName" |
| 94 | + |
| 95 | + docker run ` |
| 96 | + --entrypoint ${{ env.entry }} -di --isolation process ` |
| 97 | + --env-file .\docker\ci-windows.env ` |
| 98 | + --env-file .\docker\ninja.env ` |
| 99 | + --env "NSC_IMAGE_NAME=${{ steps.set-prefix.outputs.nscTargetTaggedImage }}" ` |
| 100 | + --name orphan --network docker_default ` |
| 101 | + -v "${{ github.workspace }}:${{ env.mount }}" ` |
| 102 | + -v "${pipeHost}:\\.\pipe\dockerd" -e "DOCKER_HOST=npipe:////./pipe/dockerd" ` |
| 103 | + -w "${{ env.mount }}" ` |
| 104 | + "${{ env.image }}:${{ matrix.tag }}" ` |
| 105 | + ${{ env.cmd }} |
| 106 | +
|
| 107 | + - name: Inspect Container |
| 108 | + run: | |
| 109 | + docker inspect orphan |
| 110 | +
|
| 111 | + - name: Container – Unpack Packages |
| 112 | + run: | |
| 113 | + docker exec orphan ` |
| 114 | + ${{ env.entry }} ${{ env.cmd }} C:\unpack.ps1 |
| 115 | +
|
| 116 | + - name: Container – Configure Project with CMake |
| 117 | + run: | |
| 118 | + mkdir profiling |
| 119 | + docker exec orphan ` |
| 120 | + ${{ env.entry }} ${{ env.cmd }} -Command cmake ` |
| 121 | + --preset ci-configure-dynamic-${{ matrix.vendor }} ` |
| 122 | + --profiling-output=profiling/cmake-profiling.json ` |
| 123 | + --profiling-format=google-trace |
| 124 | +
|
| 125 | + - name: Container – Build NSC |
| 126 | + run: | |
| 127 | + docker exec orphan ` |
| 128 | + ${{ env.entry }} ${{ env.cmd }} -Command cmake --build ` |
| 129 | + --preset ci-build-dynamic-${{ matrix.vendor }} ` |
| 130 | + -t run-compiler-explorer --config ${{ matrix.config }} |
| 131 | +
|
| 132 | + - name: Container – Install NSC |
| 133 | + run: | |
| 134 | + docker exec orphan ` |
| 135 | + ${{ env.entry }} ${{ env.cmd }} -Command cmake --install ` |
| 136 | + ${{ env.binary }} --config ${{ matrix.config }} ` |
| 137 | + --component Runtimes --prefix ${{ env.install }} |
| 138 | + docker exec orphan ` |
| 139 | + ${{ env.entry }} ${{ env.cmd }} -Command cmake --install ` |
| 140 | + ${{ env.binary }} --config ${{ matrix.config }} ` |
| 141 | + --component Executables --prefix ${{ env.install }} |
| 142 | +
|
| 143 | + - name: Container – Save NSC Image |
| 144 | + run: | |
| 145 | + docker exec orphan ` |
| 146 | + ${{ env.entry }} ${{ env.cmd }} -Command docker ` |
| 147 | + save ${{ steps.set-prefix.outputs.nscTargetTaggedImage }} | zstd -T0 -3 -f -o ${{ steps.set-prefix.outputs.prefix }}-nsc-godbolt-image.tar.zst |
| 148 | +
|
| 149 | + - name: Package left workflow artifacts |
| 150 | + run: | |
| 151 | + tar -cvf "${{ steps.set-prefix.outputs.prefix }}-profiling.tar" profiling |
| 152 | + tar -cvf "${{ steps.set-prefix.outputs.prefix }}-install.tar" ${{ env.install }} |
| 153 | +
|
| 154 | + - name: Upload NSC Godbolt Image artifact |
| 155 | + uses: actions/upload-artifact@v4 |
| 156 | + with: |
| 157 | + name: ${{ steps.set-prefix.outputs.prefix }}-nsc-godbolt-image |
| 158 | + path: ${{ steps.set-prefix.outputs.prefix }}-nsc-godbolt-image.tar.zst |
| 159 | + compression-level: 0 |
| 160 | + |
| 161 | + - name: Upload profiling artifacts |
| 162 | + uses: actions/upload-artifact@v4 |
| 163 | + with: |
| 164 | + name: ${{ steps.set-prefix.outputs.prefix }}-profiling |
| 165 | + path: ${{ steps.set-prefix.outputs.prefix }}-profiling.tar |
| 166 | + |
| 167 | + - name: Upload install artifacts |
| 168 | + uses: actions/upload-artifact@v4 |
| 169 | + with: |
| 170 | + name: ${{ steps.set-prefix.outputs.prefix }}-install |
| 171 | + path: ${{ steps.set-prefix.outputs.prefix }}-install.tar |
| 172 | + |
| 173 | + - name: Login to GHCR |
| 174 | + if: steps.set-prefix.outputs.shouldPushImage == 'True' |
| 175 | + run: echo "${{ secrets.CR_PAT }}" | docker login ghcr.io -u $env:GITHUB_ACTOR --password-stdin |
| 176 | + |
| 177 | + - name: Tag Latest image |
| 178 | + if: steps.set-prefix.outputs.shouldPushImage == 'True' |
| 179 | + run: | |
| 180 | + docker tag ${{ steps.set-prefix.outputs.nscTargetTaggedImage }} ${{ steps.set-prefix.outputs.nscTargetTaggedImageLatest }} |
| 181 | +
|
| 182 | + - name: Push images to GHCR |
| 183 | + if: steps.set-prefix.outputs.shouldPushImage == 'True' |
| 184 | + run: | |
| 185 | + docker push ${{ steps.set-prefix.outputs.nscTargetTaggedImageLatest }} |
| 186 | +
|
| 187 | + update-badges: |
| 188 | + name: Update Build & Image Badges |
| 189 | + if: ${{ always() && github.ref == 'refs/heads/master' }} |
| 190 | + needs: build-windows |
| 191 | + runs-on: windows-2022 |
| 192 | + permissions: |
| 193 | + contents: write |
| 194 | + |
| 195 | + steps: |
| 196 | + - name: Checkout |
| 197 | + uses: actions/checkout@v4 |
| 198 | + |
| 199 | + - name: Create Build Badge |
| 200 | + run: | |
| 201 | + $jobStatus = "${{ needs.build-windows.result }}" |
| 202 | + $buildMsg = if ($jobStatus -eq "success") { "passing" } else { "failing" } |
| 203 | + $buildColor = if ($jobStatus -eq "success") { "brightgreen" } else { "red" } |
| 204 | +
|
| 205 | + $buildBadge = @{ |
| 206 | + schemaVersion = 1 |
| 207 | + label = "build" |
| 208 | + message = $buildMsg |
| 209 | + color = $buildColor |
| 210 | + } | ConvertTo-Json -Depth 2 |
| 211 | +
|
| 212 | + $buildPath = ".badge-public/nabla" |
| 213 | + New-Item -ItemType Directory -Path $buildPath -Force | Out-Null |
| 214 | + $buildBadge | Set-Content -Path "$buildPath/build.json" -Encoding utf8 |
| 215 | +
|
| 216 | + - name: Create Image Size Badge |
| 217 | + run: | |
| 218 | + $owner = "${{ github.repository_owner }}" |
| 219 | + $package = "nabla-shader-compiler-godbolt" |
| 220 | + $image = "ghcr.io/${owner}/${package}:latest".ToLower() |
| 221 | + $manifest = docker manifest inspect $image | ConvertFrom-Json |
| 222 | +
|
| 223 | + if ($manifest.manifests) { |
| 224 | + $totalSize = ($manifest.manifests | Measure-Object -Property size -Sum).Sum |
| 225 | + } elseif ($manifest.layers) { |
| 226 | + $totalSize = ($manifest.layers | Measure-Object -Property size -Sum).Sum |
| 227 | + } else { |
| 228 | + Write-Error "No valid size information found in manifest." |
| 229 | + exit 1 |
| 230 | + } |
| 231 | +
|
| 232 | + $sizeMB = [Math]::Round($totalSize / 1MB, 2) |
| 233 | + $size = "$sizeMB MB" |
| 234 | +
|
| 235 | + $imageBadge = @{ |
| 236 | + schemaVersion = 1 |
| 237 | + label = $image |
| 238 | + message = $size |
| 239 | + color = "blue" |
| 240 | + } | ConvertTo-Json -Depth 2 |
| 241 | +
|
| 242 | + $imagePath = ".badge-public/packages/nabla-shader-compiler-nsc" |
| 243 | + New-Item -ItemType Directory -Path $imagePath -Force | Out-Null |
| 244 | + $imageBadge | Set-Content -Path "$imagePath/image-badge.json" -Encoding utf8 |
| 245 | +
|
| 246 | + - name: Deploy Badges |
| 247 | + uses: peaceiris/actions-gh-pages@v3 |
| 248 | + with: |
| 249 | + github_token: ${{ secrets.GITHUB_TOKEN }} |
| 250 | + publish_branch: badges |
| 251 | + publish_dir: .badge-public |
| 252 | + keep_files: true |
| 253 | + commit_message: "[CI] badges update" |
| 254 | + |
| 255 | + deploy-production: |
| 256 | + name: Deploy to production host |
| 257 | + if: ${{ always() && github.ref == 'refs/heads/master' }} |
| 258 | + needs: build-windows |
| 259 | + runs-on: ubuntu-latest |
| 260 | + |
| 261 | + steps: |
| 262 | + - name: Pull latest images, re-run containers |
| 263 | + uses: appleboy/ssh-action@v1 |
| 264 | + with: |
| 265 | + host: ${{ secrets.CE_HOST }} |
| 266 | + username: ${{ secrets.CE_USER }} |
| 267 | + key: ${{ secrets.CE_KEY }} |
| 268 | + script: | |
| 269 | + powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -NoExit -File C:\Scripts\startup-docker.ps1 |
0 commit comments