[config] Implementation of new configuration management #5207
This file contains 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 Windows Server 2019 | |
on: | |
push: | |
pull_request: | |
branches: | |
- master | |
env: | |
IS_GITHUB_SIGNING_ALLOWED: true | |
IS_JENKINS_SIGNING_ALLOWED: true | |
jobs: | |
build-windows: | |
runs-on: windows-2019 | |
env: | |
# enable starting Qt GUI Applications | |
QT_QPA_PLATFORM: offscreen | |
steps: | |
- name: Install Qt | |
uses: jurplel/install-qt-action@v3 | |
with: | |
setup-python: 'false' | |
version: '6.6.1' | |
target: 'desktop' | |
arch: 'win64_msvc2019_64' | |
- name: Install Dependencies | |
# choco install of version 1.9.3 produced a checksum error | |
run: choco install doxygen.install --version=1.9.2 | |
- name: Uninstall Chocolatey | |
run: move "$env:PROGRAMDATA\chocolatey" "$env:PROGRAMDATA\_chocolatey" | |
# - name: Install Cap’n Proto | |
# run: | | |
# mkdir "${{ runner.workspace }}/capnp" | |
# cd "${{ runner.workspace }}/capnp" | |
# git clone https://github.com/sandstorm-io/capnproto.git | |
# cd capnproto | |
# git checkout release-0.9.0 | |
# cd c++ | |
# mkdir _build | |
# cd _build | |
# cmake .. -G "Visual Studio 16 2019" -A x64 | |
# cmake --build . --parallel --config Release | |
# cmake --build . --target install --config Release | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
submodules: 'true' | |
fetch-depth: 0 | |
- name: Create Python virtualenv | |
run: | | |
mkdir "${{ runner.workspace }}\_build\complete\.venv\" | |
# At the moment (2021-10-27) there is no official Python 3.10 lxml package available on pypi. Thus we use python 3.9. | |
py -3.9 -m venv "${{ runner.workspace }}\.venv" | |
CALL "${{ runner.workspace }}\.venv\Scripts\activate.bat" | |
echo Upgrading pip | |
python -m pip install --upgrade pip | |
pip install wheel | |
echo Installing python requirements | |
pip install -r "%GITHUB_WORKSPACE%\doc\requirements.txt" | |
shell: cmd | |
- name: CMake SDK | |
run: | | |
mkdir "${{ runner.workspace }}\_build\sdk\" | |
cd "${{ runner.workspace }}/_build/sdk" | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 ^ | |
-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=cmake/submodule_dependencies.cmake ^ | |
-DHAS_HDF5=ON ^ | |
-DHAS_QT=ON ^ | |
-DHAS_CURL=OFF ^ | |
-DHAS_CAPNPROTO=OFF ^ | |
-DHAS_FTXUI=ON ^ | |
-DBUILD_DOCS=OFF ^ | |
-DBUILD_APPS=OFF ^ | |
-DBUILD_SAMPLES=OFF ^ | |
-DBUILD_TIME=ON ^ | |
-DBUILD_PY_BINDING=OFF ^ | |
-DBUILD_CSHARP_BINDING=OFF ^ | |
-DBUILD_ECAL_TESTS=OFF ^ | |
-DECAL_INCLUDE_PY_SAMPLES=OFF ^ | |
-DECAL_INSTALL_SAMPLE_SOURCES=OFF ^ | |
-DECAL_JOIN_MULTICAST_TWICE=OFF ^ | |
-DECAL_NPCAP_SUPPORT=ON ^ | |
-DECAL_THIRDPARTY_BUILD_CMAKE_FUNCTIONS=ON ^ | |
-DECAL_THIRDPARTY_BUILD_PROTOBUF=ON ^ | |
-DECAL_THIRDPARTY_BUILD_SPDLOG=ON ^ | |
-DECAL_THIRDPARTY_BUILD_TINYXML2=ON ^ | |
-DECAL_THIRDPARTY_BUILD_FINEFTP=OFF ^ | |
-DECAL_THIRDPARTY_BUILD_CURL=OFF ^ | |
-DECAL_THIRDPARTY_BUILD_GTEST=OFF ^ | |
-DECAL_THIRDPARTY_BUILD_HDF5=ON ^ | |
-DECAL_THIRDPARTY_BUILD_RECYCLE=ON ^ | |
-DECAL_THIRDPARTY_BUILD_TCP_PUBSUB=ON ^ | |
-DECAL_THIRDPARTY_BUILD_QWT=OFF ^ | |
-DECAL_THIRDPARTY_BUILD_YAML-CPP=OFF ^ | |
-DECAL_THIRDPARTY_BUILD_UDPCAP=ON ^ | |
-DBUILD_SHARED_LIBS=OFF ^ | |
-DCMAKE_PREFIX_PATH="%ProgramFiles%/Cap'n Proto/lib/cmake/CapnProto" ^ | |
-DCMAKE_BUILD_TYPE=Debug ^ | |
-DCPACK_PACK_WITH_INNOSETUP=OFF | |
shell: cmd | |
- name: CMake Complete | |
run: | | |
CALL "${{ runner.workspace }}\.venv\Scripts\activate.bat" | |
cd "${{ runner.workspace }}/_build/complete" | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 ^ | |
-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=cmake/submodule_dependencies.cmake ^ | |
-DHAS_HDF5=ON ^ | |
-DHAS_QT=ON ^ | |
-DHAS_CURL=ON ^ | |
-DHAS_CAPNPROTO=OFF ^ | |
-DHAS_FTXUI=ON ^ | |
-DBUILD_DOCS=ON ^ | |
-DBUILD_APPS=ON ^ | |
-DBUILD_SAMPLES=ON ^ | |
-DBUILD_TIME=ON ^ | |
-DBUILD_PY_BINDING=ON ^ | |
-DBUILD_CSHARP_BINDING=ON ^ | |
-DBUILD_ECAL_TESTS=ON ^ | |
-DECAL_INCLUDE_PY_SAMPLES=OFF ^ | |
-DECAL_INSTALL_SAMPLE_SOURCES=ON ^ | |
-DECAL_JOIN_MULTICAST_TWICE=OFF ^ | |
-DECAL_NPCAP_SUPPORT=ON ^ | |
-DECAL_THIRDPARTY_BUILD_CMAKE_FUNCTIONS=ON ^ | |
-DECAL_THIRDPARTY_BUILD_PROTOBUF=ON ^ | |
-DECAL_THIRDPARTY_BUILD_SPDLOG=ON ^ | |
-DECAL_THIRDPARTY_BUILD_TINYXML2=ON ^ | |
-DECAL_THIRDPARTY_BUILD_FINEFTP=ON ^ | |
-DECAL_THIRDPARTY_BUILD_CURL=ON ^ | |
-DECAL_THIRDPARTY_BUILD_GTEST=ON ^ | |
-DECAL_THIRDPARTY_BUILD_HDF5=ON ^ | |
-DECAL_THIRDPARTY_BUILD_RECYCLE=ON ^ | |
-DECAL_THIRDPARTY_BUILD_TCP_PUBSUB=ON ^ | |
-DECAL_THIRDPARTY_BUILD_QWT=ON ^ | |
-DECAL_THIRDPARTY_BUILD_YAML-CPP=ON ^ | |
-DECAL_THIRDPARTY_BUILD_UDPCAP=ON ^ | |
-DBUILD_SHARED_LIBS=OFF ^ | |
-DCMAKE_PREFIX_PATH="%ProgramFiles%/Cap'n Proto/lib/cmake/CapnProto" ^ | |
-DCMAKE_BUILD_TYPE=Release ^ | |
-DCPACK_PACK_WITH_INNOSETUP=ON | |
mkdir "%ALLUSERSPROFILE%\eCAL" | |
copy "%GITHUB_WORKSPACE%\ecal\core\cfg\ecal.ini" "%ALLUSERSPROFILE%\eCAL" | |
shell: cmd | |
- name: Build SDK | |
run: cmake --build . --config Debug | |
working-directory: ${{ runner.workspace }}/_build/sdk | |
- name: Build Release | |
run: cmake --build . --config Release | |
working-directory: ${{ runner.workspace }}/_build/complete | |
# Create Python. | |
# The strang-looking double-cmake is an ugly workaround to force CMake to | |
# re-find Python, after we have changed the venv from the outside. The | |
# alternative would be to clean everything, which would cause an unnecessary | |
# rebuild of eCAL and HDF5 for each python Version. | |
- name: Build Python 3.12 Wheel | |
run: | | |
mkdir ".venv_312" | |
py -3.12 -m venv ".venv_312" | |
CALL ".venv_312\Scripts\activate.bat" | |
pip install wheel setuptools | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=FIRST | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=ONLY | |
cmake --build . --target create_python_wheel --config Release | |
shell: cmd | |
working-directory: ${{ runner.workspace }}/_build/complete | |
- name: Build Python 3.11 Wheel | |
run: | | |
mkdir ".venv_311" | |
py -3.11 -m venv ".venv_311" | |
CALL ".venv_311\Scripts\activate.bat" | |
pip install wheel | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=FIRST | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=ONLY | |
cmake --build . --target create_python_wheel --config Release | |
shell: cmd | |
working-directory: ${{ runner.workspace }}/_build/complete | |
- name: Build Python 3.10 Wheel | |
run: | | |
mkdir ".venv_310" | |
py -3.10 -m venv ".venv_310" | |
CALL ".venv_310\Scripts\activate.bat" | |
pip install wheel | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=FIRST | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=ONLY | |
cmake --build . --target create_python_wheel --config Release | |
shell: cmd | |
working-directory: ${{ runner.workspace }}/_build/complete | |
- name: Build Python 3.9 Wheel | |
run: | | |
mkdir ".venv_39" | |
py -3.9 -m venv ".venv_39" | |
CALL ".venv_39\Scripts\activate.bat" | |
pip install wheel | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=FIRST | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=ONLY | |
cmake --build . --target create_python_wheel --config Release | |
shell: cmd | |
working-directory: ${{ runner.workspace }}/_build/complete | |
- name: Build Python 3.8 Wheel | |
run: | | |
mkdir ".venv_38" | |
py -3.8 -m venv ".venv_38" | |
CALL ".venv_38\Scripts\activate.bat" | |
pip install wheel | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=FIRST | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=ONLY | |
cmake --build . --target create_python_wheel --config Release | |
shell: cmd | |
working-directory: ${{ runner.workspace }}/_build/complete | |
- name: Build Python 3.7 Wheel | |
run: | | |
mkdir ".venv_37" | |
py -3.7 -m venv ".venv_37" | |
CALL ".venv_37\Scripts\activate.bat" | |
pip install wheel | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=FIRST | |
cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=ONLY | |
cmake --build . --target create_python_wheel --config Release | |
shell: cmd | |
working-directory: ${{ runner.workspace }}/_build/complete | |
# - name: Build Documentation C | |
# run: cmake --build . --target documentation_c | |
# working-directory: ${{ runner.workspace }}/_build | |
# | |
# - name: Build Documentation C++ | |
# run: cmake --build . --target documentation_cpp | |
# working-directory: ${{ runner.workspace }}/_build | |
- name: Run Tests | |
run: ctest -C Release -V | |
working-directory: ${{ runner.workspace }}/_build/complete | |
- name: Pack SDK | |
run: cpack -C Debug | |
working-directory: ${{ runner.workspace }}/_build/sdk | |
- name: Pack complete setup | |
run: cpack -C Release | |
working-directory: ${{ runner.workspace }}/_build/complete | |
- name: Detect certificate | |
id: cert | |
if: env.IS_GITHUB_SIGNING_ALLOWED == 'true' | |
run: | | |
if ($Env:CERT_BODY -and $Env:CERT_PSWD -and $Env:CERT_ALGO -and $Env:CERT_HASH) { | |
Write-Output "ATTENTION: a certificate is available" | |
Write-Output "IS_GITHUB_SIGNING_ENABLED=true" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append | |
} else { | |
Write-Output "WARNING: a certificate is not available" | |
} | |
env: | |
CERT_BODY: ${{ secrets.CERT_BODY }} | |
CERT_PSWD: ${{ secrets.CERT_PSWD }} | |
CERT_ALGO: ${{ secrets.CERT_ALGO }} | |
CERT_HASH: ${{ secrets.CERT_HASH }} | |
# https://github.com/OrhanKupusoglu/code-sign-action | |
- name: Sign the installer | |
if: env.IS_GITHUB_SIGNING_ENABLED == 'true' | |
uses: OrhanKupusoglu/[email protected] | |
with: | |
cert_body: ${{ secrets.CERT_BODY }} | |
cert_pswd: ${{ secrets.CERT_PSWD }} | |
cert_algo: ${{ secrets.CERT_ALGO }} | |
cert_hash: ${{ secrets.CERT_HASH }} | |
folder: ${{ runner.workspace }}/_build/complete/_deploy | |
debug: false | |
- name: Upload Windows setup | |
uses: actions/upload-artifact@v4 | |
with: | |
name: windows-setup | |
path: ${{ runner.workspace }}/_build/complete/_deploy/*.exe | |
- name: Upload Python Wheels | |
uses: actions/upload-artifact@v4 | |
with: | |
name: windows-python-wheels | |
path: ${{ runner.workspace }}/_build/complete/_deploy/*.whl | |
# -------------------------------------------------------------------------------------------------- | |
sign-windows-installer: | |
runs-on: windows-2019 | |
needs: build-windows | |
steps: | |
# Download the installer from the previous job | |
- name: Download Windows setup | |
uses: actions/download-artifact@v4 | |
with: | |
name: windows-setup | |
path: ${{ runner.workspace }}/_build/complete/_deploy | |
- name: Sign the installer on Eclipse CI | |
if: env.IS_JENKINS_SIGNING_ALLOWED == 'true' && env.JENKINS_USERNAME != '' && env.JENKINS_API_TOKEN != '' && env.JENKINS_JOB_TOKEN != '' | |
run: | | |
$LS_OUT = ls *.exe | |
$ASSET_NAME = "$($LS_OUT.Name)" | |
$ASSET_NAME_OLD = "$($ASSET_NAME).old" | |
$ASSET_NAME_NEW = "$ASSET_NAME" | |
$JENKINS_JOB = 'gh_auto_file' | |
$JENKINS_BASE_URL = "https://ci.eclipse.org/ecal" | |
$JENKINS_CRUMB_URL = "$JENKINS_BASE_URL/crumbIssuer/api/json" | |
$JENKINS_JOB_URL = "$JENKINS_BASE_URL/job/$JENKINS_JOB" | |
$JENKINS_TRIGGER_URL = "$JENKINS_JOB_URL/buildWithParameters?token=$Env:JENKINS_JOB_TOKEN" | |
$WAIT_FOR_JENKINS_SEC = 10 | |
$COUNTER_LIMIT = 30 | |
$RESPONSE_CODE = 0 | |
$CRUMB_ID = '' | |
$CRUMB_FIELD = '' | |
$CRUMB_COOKIE = '' | |
$COUNTER = 0 | |
$QUEUE_URL = '' | |
$BUILD_NUM = 0 | |
$BUILD_URL = '' | |
Write-Output "-- get a Jenkins crumb & cookie" | |
$AUTH_CREDENTIAL = $Env:JENKINS_USERNAME + ':' + $Env:JENKINS_API_TOKEN | |
$AUTH_ENCODED = [System.Text.Encoding]::UTF8.GetBytes($AUTH_CREDENTIAL) | |
$AUTH_INFO = [System.Convert]::ToBase64String($AUTH_ENCODED) | |
$CRUMB_HEADERS = @{ | |
'Authorization'="Basic $($AUTH_INFO)" | |
} | |
$RESPONSE = Invoke-WebRequest -Uri $JENKINS_CRUMB_URL -Method GET -Headers $CRUMB_HEADERS | |
$RES_CODE = $RESPONSE.StatusCode | |
Write-Output " ++ Jenkins crumb retrieval - HTTP status code: $RES_CODE" | |
if ($RES_CODE -ge 200 -and $RES_CODE -lt 300) { | |
$JSON_CONTENT = $RESPONSE.Content | ConvertFrom-Json | |
$CRUMB_ID = $JSON_CONTENT.crumb | |
$CRUMB_FIELD = $JSON_CONTENT.crumbRequestField | |
$CRUMB_COOKIE = $RESPONSE.Headers['Set-Cookie'] | |
#Write-Output " ++ Jenkins crumb: '$CRUMB_ID'" | |
#Write-Output " ++ Jenkins cookie: '$CRUMB_COOKIE'" | |
} else { | |
Write-Output " ** determination of the Jenkins crumb failed" | |
Exit 1 | |
} | |
Write-Output "-- trigger a new build of '$JENKINS_JOB' with installer '$ASSET_NAME'" | |
$TRIGGER_HEADERS = @{ | |
'Authorization'="Basic $($AUTH_INFO)" | |
'Cookie'=$CRUMB_COOKIE | |
$CRUMB_FIELD=$CRUMB_ID | |
} | |
$FORM = @{ | |
'GH_FILE_NAME'= $ASSET_NAME | |
'GH_EXECUTABLE'= Get-Item -Path $ASSET_NAME | |
} | |
$RESPONSE = Invoke-WebRequest -Uri $JENKINS_TRIGGER_URL -Method POST -Headers $TRIGGER_HEADERS -Form $FORM | |
$RES_CODE = $RESPONSE.StatusCode | |
Write-Output " ++ trigger build - HTTP status code: $RES_CODE" | |
if ($RES_CODE -ge 200 -and $RES_CODE -lt 300) { | |
$QUEUE_URL = $RESPONSE.Headers.location | |
$QUEUE_URL = "$($QUEUE_URL)api/json/" | |
Write-Output " ++ queue URL: $QUEUE_URL" | |
} else { | |
Write-Output " ** trigger failure" | |
Exit 1 | |
} | |
Write-Output "-- get the new build number" | |
while ($true) { | |
$COUNTER++ | |
if ($COUNTER -gt $COUNTER_LIMIT) { | |
Write-Output " ** determination of the new build number failed after $COUNTER_LIMIT tries" | |
Exit 1 | |
} | |
$RESPONSE = Invoke-WebRequest -Uri $QUEUE_URL | |
$RES_CODE = $RESPONSE.StatusCode | |
Write-Output " ++ build number retrieval - HTTP status code: $RES_CODE" | |
if ($RES_CODE -ge 200 -and $RES_CODE -lt 300) { | |
$JSON_CONTENT = $RESPONSE.Content | ConvertFrom-Json | |
$EXECUTABLE = $JSON_CONTENT.executable | |
$BUILD_NUM = $EXECUTABLE.number | |
if ($BUILD_NUM) { | |
Write-Output " ++ #build number: $BUILD_NUM" | |
$BUILD_URL = $EXECUTABLE.url | |
Break | |
} else { | |
Write-Output " ++ ... pending, wait for $WAIT_FOR_JENKINS_SEC s" | |
Start-Sleep -s $WAIT_FOR_JENKINS_SEC | |
} | |
} else { | |
Write-Output " ** determination of the build number failed, trying again after $WAIT_FOR_JENKINS_SEC s" | |
Start-Sleep -s $WAIT_FOR_JENKINS_SEC | |
} | |
} | |
$JENKINS_STATUS_URL = "$($BUILD_URL)api/json" | |
Write-Output "-- check build status of #Build $BUILD_NUM with $JENKINS_STATUS_URL" | |
while ($true) { | |
$RESPONSE = Invoke-WebRequest -Uri $JENKINS_STATUS_URL | |
$RES_CODE = $RESPONSE.StatusCode | |
Write-Output " ++ status check - HTTP status code: $RES_CODE" | |
if ($RES_CODE -ge 200 -and $RES_CODE -lt 300) { | |
$CONTENT = ConvertFrom-Json $RESPONSE.Content | |
$NUMBER = $CONTENT | Select-Object -expand 'number' | |
if ($NUMBER -eq $BUILD_NUM) { | |
$BUILDING = $CONTENT | Select-Object -expand 'building' | |
if ($BUILDING) { | |
Write-Output " ++ ... building, wait for $WAIT_FOR_JENKINS_SEC s" | |
Start-Sleep -s $WAIT_FOR_JENKINS_SEC | |
} else { | |
$RESULT = $CONTENT | Select-Object -expand 'result' | |
if ($RESULT -eq 'SUCCESS') { | |
Write-Output " ++ build success, asset name: '$ASSET_NAME'" | |
Break | |
} else { | |
Write-Output " ** build failure" | |
Exit 1 | |
} | |
} | |
} else { | |
Write-Output " ++ ... pending, wait for $WAIT_FOR_JENKINS_SEC s" | |
Start-Sleep -s $WAIT_FOR_JENKINS_SEC | |
} | |
} else { | |
Write-Output " ** status check failure" | |
Exit 1 | |
} | |
} | |
$JENKINS_DOWNLOAD_URL = "$JENKINS_JOB_URL/$BUILD_NUM/artifact/$ASSET_NAME" | |
Write-Output "-- download the newly-signed Windows installer from #Build $BUILD_NUM with $JENKINS_DOWNLOAD_URL" | |
Rename-Item -Path "$ASSET_NAME" -NewName "$ASSET_NAME_OLD" | |
$RESPONSE = Invoke-WebRequest -Uri $JENKINS_DOWNLOAD_URL -OutFile $ASSET_NAME_NEW -PassThru | |
$RES_CODE = $RESPONSE.StatusCode | |
Write-Output " ++ download installer - HTTP status code: $RES_CODE" | |
if ($RES_CODE -ge 200 -and $RES_CODE -lt 300) { | |
Write-Output "IS_DOWNLOAD_AVAILABLE=true" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append | |
Write-Output "ASSET_NAME=$ASSET_NAME" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append | |
Write-Output " ++ downloaded signed installer: '$ASSET_NAME'" | |
} else { | |
Write-Output " ** download failure" | |
Exit 1 | |
} | |
env: | |
JENKINS_USERNAME: ${{ secrets.JENKINS_USERNAME }} | |
JENKINS_API_TOKEN: ${{ secrets.JENKINS_API_TOKEN }} | |
JENKINS_JOB_TOKEN: ${{ secrets.JENKINS_TOKEN_GH_FILE }} | |
working-directory: ${{ runner.workspace }}/_build/complete/_deploy | |
- name: Upload Windows setup signed on Eclipse CI | |
if: env.IS_DOWNLOAD_AVAILABLE == 'true' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: windows-setup-signed | |
path: ${{ runner.workspace }}/_build/complete/_deploy/${{ env.ASSET_NAME }} |