diff --git a/.github/workflows/msvc_build_ue4ss.yml b/.github/workflows/msvc_build_ue4ss.yml new file mode 100644 index 000000000..6ede915c4 --- /dev/null +++ b/.github/workflows/msvc_build_ue4ss.yml @@ -0,0 +1,125 @@ +# Summary +# This reusable workflow handles the installation of xmake, cloning of the repo, building of UE4SS, and uploading of artifacts. +# Any future workflows/tasks that require UE4SS to be built should call this reusable workflow to ensure consistency. +name: "Build UE4SS" +permissions: + contents: read +on: + workflow_call: + inputs: + build-mode: + description: 'Which UE4SS Mode to build. This is passed to xmake config -m ' + type: string + required: true + commit-sha: + description: 'Commit to build' + type: string + required: true + should-upload-artifact: + description: 'Should build output be uploaded as an artifact?' + type: boolean + default: false + artifact-list: + description: 'List of targets to upload artifacts for' + type: string + default: '["UE4SS"]' + artifact-retention-days: + description: 'How many days to retain artifacts' + type: number + default: 7 +defaults: + run: + shell: pwsh +jobs: + build: + runs-on: windows-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + submodules: recursive # Clone the submodule so we can query xmake on the entire project. + token: ${{ secrets.UEPSEUDO_PAT }} + ref: ${{inputs.commit-sha}} + + # Store the current week (00-53) to use as part of the xmake cache key. + # This saves us from having to detect older caches and delete them. + - name: Get current week as package key + id: cache_key + run: echo "key=$(date +'%W')" >> $GITHUB_OUTPUT + shell: bash + + # Force xmake to a specific folder (for cache) + - name: Set xmake env + run: echo "XMAKE_GLOBALDIR=${{ runner.tool_cache }}/xmake-global" >> $env:GITHUB_ENV + + # Specifically use MSVC toolset v19.39.33523 + - name: Install VS2022 BuildTools 17.9.7 + run: choco install -y visualstudio2022buildtools --version=117.9.7.0 --params "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --installChannelUri https://aka.ms/vs/17/release/180911598_-255012421/channel" + + - name: Setup xmake + uses: xmake-io/github-action-setup-xmake@v1 + with: + xmake-version: '2.9.3' + + - name: Update xmake repository + run: xmake repo --update + + # Fetch xmake dephash. This is a xmake provided hash that is calculated based on package versions and configurations. + - name: Retrieve dependencies hash + id: dep_hash + run: echo "hash=$(xmake l utils.ci.packageskey)" >> $env:GITHUB_OUTPUT + + # Cache xmake dependencies + - name: Restore cached xmake dependencies + id: restore-depcache + uses: actions/cache/restore@v4 + with: + path: ${{ env.XMAKE_GLOBALDIR }}/.xmake/packages + # Example key: MSVC-Game__Shipping__Win64-42d5ac22284a460e96b6cab018d6b7b5-W23 + key: MSVC-${{ inputs.build-mode }}-${{ steps.dep_hash.outputs.hash }}-W${{ steps.cache_key.outputs.key }} + + # Setup compilation mode and install project dependencies. + # The additional powershell commands allow us to use MSVC toolset v19.39.33523 + - name: Configure xmake and install dependencies + run: | + Import-Module 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\Tools\Microsoft.VisualStudio.DevShell.dll' + Enter-VsDevShell -VsInstallPath 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools' -DevCmdArguments '-arch=x64 -host_arch=x64' + + xmake config -vD -m "${{inputs.build-mode}}" -y + + - name: Save cached xmake dependencies + if: ${{ !steps.restore-depcache.outputs.cache-hit }} + uses: actions/cache/save@v4 + with: + path: ${{ env.XMAKE_GLOBALDIR }}/.xmake/packages + key: ${{ steps.restore-depcache.outputs.cache-primary-key }} + + - name: Build + id: build + run: > + xmake build -y + + # Use the `artifact-list` input to determine which files should be uploaded as an artifact. + - name: Calculate Files For Artifact Inclusion + id: calc-files-artifact + run: | + $files_to_upload = (xmake ci --dump=targets) | jq --raw-output --argjson config '${{inputs.artifact-list}}' '. as $in | $config[] | $in[.] | .[]' + + $artifact_dir = New-Item -Path '${{runner.temp}}/ue4ss_artifacts/' -ItemType Directory -Force + + foreach ($file in $files_to_upload) { + Write-Host $file; Copy-Item "$file" -Destination $artifact_dir + } + + echo "artifact_dir=$artifact_dir" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append + + - name: Upload a Build Artifact + id: upload-artifact + uses: actions/upload-artifact@v4.3.3 + if: ${{inputs.should-upload-artifact == true}} + with: + name: MSVC-${{inputs.build-mode}} + path: | + ${{ steps.calc-files-artifact.outputs.artifact_dir }} + retention-days: ${{fromJSON(inputs.artifact-retention-days)}} + overwrite: true diff --git a/.github/workflows/ue4ss-ci.yml b/.github/workflows/ue4ss-ci.yml new file mode 100644 index 000000000..87844d7ef --- /dev/null +++ b/.github/workflows/ue4ss-ci.yml @@ -0,0 +1,108 @@ +# This workflow automates the build process for all modes of the UE4SS project whenever a pull request is made. +# It dynamically calculates the build matrix based on the modes defined in the project and reports artifacts to the PR comments. + +name: Build All Modes +permissions: + contents: write + pull-requests: write # For adding comments to PR. +on: + pull_request: + branches: + - 'main' + paths-ignore: + - 'README.md' + - 'docs/**' + - 'docs-export/**' + +# Ensure that rapid pushes to the pull request branch don't trigger this workflow multiple times. +# We only care about executing this workflow for that 'latest' commit on a PR. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + # Dynamically calculate which modes to build. + # We also need to determine which modes should upload artifacts. + calculate-matrix: + name: Calculate job matrix + runs-on: ubuntu-latest + outputs: + # JSON array with the following schema: + # [ + # { + # "mode": "Game__Shipping__Win64", + # "artifact": false + # }, + # ... + # ] + matrix: ${{ steps.calculate-artifacts.outputs.matrix }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive # Clone the submodule so we can query xmake on the entire project. + token: ${{ secrets.UEPSEUDO_PAT }} + + # Build modes are supplied by xmake, so we have to download and setup the xmake environment. + - name: Setup xmake + uses: xmake-io/github-action-setup-xmake@v1 + with: + xmake-version: "2.9.3" + actions-cache-folder: '.xmake-cache' # This auto-cache functionality only works on linux runners. + + # `xmake ci --dump=modes` returns a JSON array of all UE4SS modes that xmake knows how to build. + - name: Get xmake Modes + id: get-xmake-modes + shell: pwsh + run: | + $modes = (xmake ci --dump=modes) + echo "all_modes=$modes" >> $env:GITHUB_OUTPUT + + # Construct the build matrix by adding `"artifact": true/false` to each mode. + - name: Finalize Mode Matrix + uses: actions/github-script@v7 + id: calculate-artifacts + env: + ALL_MODES: '${{steps.get-xmake-modes.outputs.all_modes}}' + REQUESTED_MODES: '["Game__Shipping__Win64", "Game__Debug__Win64"]' + with: + result-encoding: string + script: | + const { ALL_MODES, REQUESTED_MODES } = process.env; + const requestedModes = JSON.parse(REQUESTED_MODES) + const modeSchema = JSON.parse(ALL_MODES).map(m => ({mode: m, artifact: requestedModes.includes(m) })); + core.setOutput('matrix', JSON.stringify(modeSchema)); + + # Build UE4SS for each mode we received from the `calculate_matrix` job. + build: + name: ${{ matrix.mode }} + needs: [ calculate-matrix ] # Ensure the mode/artifact matrix has been generated before we launch this job. + strategy: + fail-fast: false # Disable fast failing because we want to cancel other modes if one fails. + matrix: + # Use our generated matrix to populate the `include` array. + include: ${{ fromJSON(needs.calculate-matrix.outputs.matrix) }} + # Run our reusable workflow for each mode in our matrix. + uses: ./.github/workflows/msvc_build_ue4ss.yml + secrets: inherit # Inherit secrets from this workflow to safely pass `secrets.UE4SS_PAT` to our reusable workflow. + with: + build-mode: ${{ matrix.mode }} + commit-sha: ${{ github.sha }} # This is the SHA of the PR merge result, not the HEAD of the PR branch! + should-upload-artifact: ${{ matrix.artifact }} + # List that declares which xmake targets should have their output uploaded as an artifact. + # Available targets should be in the list generated by `xmake ci --dump=targets`. + # This specifies that the `UE4SS` target should upload its target file and symbol file. + # Ex. UE4SS.dll + UE4SS.pdb + artifact-list: '["UE4SS"]' + artifact-retention-days: 14 + + # Report artifacts as a pull request comment. + report-artifacts: + if: ${{ always() && contains(needs.calculate-matrix.result, 'success') }} + needs: [calculate-matrix, build] + runs-on: ubuntu-latest + steps: + - name: "Report Artifacts" + uses: bitonality/PRtifact@v0.1.0 + with: + comment-mode: 'CreateOrUpdate'