Custom Windows Client Generator #364
This file contains hidden or 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: Custom Windows Client Generator | |
run-name: Custom Windows Client Generator | |
on: | |
workflow_dispatch: | |
inputs: | |
server: | |
description: 'Rendezvous Server' | |
required: true | |
default: '' | |
type: string | |
key: | |
description: 'Public Key' | |
required: true | |
default: '' | |
type: string | |
apiServer: | |
description: 'API Server' | |
required: true | |
default: '' | |
type: string | |
custom: | |
description: "Custom JSON" | |
required: true | |
default: '' | |
type: string | |
uuid: | |
description: "uuid of request" | |
required: true | |
default: '' | |
type: string | |
iconlink: | |
description: "icon link" | |
required: false | |
default: 'false' | |
type: string | |
logolink: | |
description: "logo link" | |
required: false | |
default: 'false' | |
type: string | |
appname: | |
description: "app name" | |
required: true | |
default: 'rustdesk' | |
type: string | |
filename: | |
description: "Filename" | |
required: true | |
default: 'rustdesk' | |
type: string | |
extras: | |
description: "extra inputs in json" | |
required: true | |
default: '{}' | |
type: string | |
env: | |
SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html | |
RUST_VERSION: "1.75" # sciter failed on m1 with 1.78 because of https://blog.rust-lang.org/2024/03/30/i128-layout-update.html | |
CARGO_NDK_VERSION: "3.1.2" | |
SCITER_ARMV7_CMAKE_VERSION: "3.29.7" | |
SCITER_NASM_DEBVERSION: "2.14-1" | |
LLVM_VERSION: "15.0.6" | |
FLUTTER_VERSION: "3.24.5" | |
ANDROID_FLUTTER_VERSION: "3.24.5" | |
FLUTTER_RUST_BRIDGE_VERSION: "1.80.1" | |
# for arm64 linux because official Dart SDK does not work | |
FLUTTER_ELINUX_VERSION: "3.16.9" | |
TAG_NAME: "${{ inputs.upload-tag }}" | |
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite" | |
# vcpkg version: 2024.07.12 | |
VCPKG_COMMIT_ID: "b2cb0da531c2f1f740045bfe7c4dac59f0b2b69c" | |
VERSION: "${{ fromJson(inputs.extras).version }}" | |
NDK_VERSION: "r27c" | |
#signing keys env variable checks | |
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}" | |
MACOS_P12_BASE64: "${{ secrets.MACOS_P12_BASE64 }}" | |
# To make a custom build with your own servers set the below secret values | |
RS_PUB_KEY: "${{ inputs.key }}" | |
RENDEZVOUS_SERVER: "${{ inputs.server }}" | |
CUSTOM: "${{ inputs.custom }}" | |
UUIDFOLDER: "${{ inputs.uuid }}" | |
API_SERVER: "${{ inputs.apiServer }}" | |
UPLOAD_ARTIFACT: 'true' | |
SIGN_BASE_URL: "${{ secrets.SIGN_BASE_URL }}" | |
STATUS_URL: "${{ secrets.GENURL }}/updategh" | |
jobs: | |
generate-bridge: | |
uses: ./.github/workflows/bridge.yml | |
with: | |
version: ${{ fromJson(inputs.extras).version }} | |
build-RustDeskTempTopMostWindow: | |
uses: ./.github/workflows/third-party-RustDeskTempTopMostWindow.yml | |
with: | |
upload-artifact: true | |
target: windows-2022 | |
configuration: Release | |
platform: x64 | |
target_version: Windows10 | |
strategy: | |
fail-fast: false | |
build-for-windows-flutter: | |
name: Build Windows | |
needs: [build-RustDeskTempTopMostWindow, generate-bridge] | |
runs-on: ${{ matrix.job.os }} | |
strategy: | |
fail-fast: false | |
matrix: | |
job: | |
# - { target: i686-pc-windows-msvc , os: windows-2022 } | |
# - { target: x86_64-pc-windows-gnu , os: windows-2022 } | |
- { | |
target: x86_64-pc-windows-msvc, | |
os: windows-2022, | |
arch: x86_64, | |
vcpkg-triplet: x64-windows-static, | |
} | |
# - { target: aarch64-pc-windows-msvc, os: windows-2022, arch: aarch64 } | |
steps: | |
- name: Export GitHub Actions cache environment variables | |
uses: actions/github-script@v6 | |
with: | |
script: | | |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); | |
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); | |
- name: Set rdgen value | |
if: ${{ fromJson(inputs.extras).rdgen == 'true' }} | |
run: | | |
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $env:GITHUB_ENV | |
- name: Set rdgen value | |
if: ${{ fromJson(inputs.extras).rdgen == 'false' }} | |
run: | | |
echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $env:GITHUB_ENV | |
- name: Report Status | |
uses: fjogeleit/http-request-action@v1 | |
with: | |
url: ${{ env.STATUS_URL }} | |
method: 'POST' | |
customHeaders: '{"Content-Type": "application/json"}' | |
data: '{"uuid": "${{ inputs.uuid }}", "status": "5% complete"}' | |
- name: Checkout source code | |
if: ${{ env.VERSION != 'master' }} | |
uses: actions/checkout@v4 | |
with: | |
repository: rustdesk/rustdesk | |
ref: refs/tags/${{ env.VERSION }} | |
- name: Checkout source code | |
if: ${{ env.VERSION == 'master' }} | |
uses: actions/checkout@v4 | |
with: | |
repository: rustdesk/rustdesk | |
- name: Restore bridge files | |
uses: actions/download-artifact@master | |
with: | |
name: bridge-artifact | |
path: ./ | |
- name: Install ImageMagick on Windows | |
run: | | |
choco install -y imagemagick.app --no-progress | |
Get-ChildItem -Path "${env:ProgramFiles}" | % { $_.FullName } | Select-String -Pattern "[\/\\]ImageMagick[^\/\\]*$" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8 | |
- name: change appname to custom | |
if: inputs.appname != 'rustdesk' | |
continue-on-error: true | |
shell: bash | |
run: | | |
# ./Cargo.toml | |
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./Cargo.toml | |
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./Cargo.toml | |
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./Cargo.toml | |
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./Cargo.toml | |
# ./libs/portable/Cargo.toml | |
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml | |
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml | |
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml | |
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./libs/portable/Cargo.toml | |
# ./flutter/windows/runner/Runner.rc | |
sed -i -e 's|"RustDesk Remote Desktop"|"${{ inputs.appname }}"|' ./flutter/windows/runner/Runner.rc | |
sed -i -e 's|VALUE "InternalName", "rustdesk" "\0"|VALUE "InternalName", "${{ inputs.appname }}" "\0"|' ./flutter/windows/runner/Runner.rc | |
sed -i -e 's|"Copyright © 2024 Purslane Ltd. All rights reserved."|"Copyright © 2024"|' ./flutter/windows/runner/Runner.rc | |
sed -i -e 's|"rustdesk.exe"|"${{ inputs.filename }}"|' ./flutter/windows/runner/Runner.rc | |
sed -i -e 's|"RustDesk"|"${{ inputs.appname }}"|' ./flutter/windows/runner/Runner.rc | |
# ./src/lang/en.rs | |
sed -i -e 's|RustDesk|${{ inputs.appname }}|' ./src/lang/en.rs | |
- name: change url to custom | |
if: fromJson(inputs.extras).urlLink != 'https://rustdesk.com' | |
continue-on-error: true | |
shell: bash | |
run: | | |
sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ fromJson(inputs.extras).urlLink }}|' ./build.py | |
sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart | |
sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart | |
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart | |
sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart | |
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart | |
sed -i -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart | |
- name: allow custom.txt | |
continue-on-error: true | |
shell: bash | |
run: | | |
sed -i -e '/const KEY:/,/};/d' ./src/common.rs | |
sed -i -e '/let Ok(data) = sign::verify(&data, &pk)/,/};/d' ./src/common.rs | |
# ./flutter/pubspec.yaml | |
sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml | |
- name: Install LLVM and Clang | |
uses: KyleMayes/install-llvm-action@v1 | |
with: | |
version: ${{ env.LLVM_VERSION }} | |
- name: Report Status | |
uses: fjogeleit/http-request-action@v1 | |
with: | |
url: ${{ env.STATUS_URL }} | |
method: 'POST' | |
customHeaders: '{"Content-Type": "application/json"}' | |
data: '{"uuid": "${{ inputs.uuid }}", "status": "10% complete"}' | |
- name: Install flutter | |
uses: subosito/flutter-action@v2.12.0 #https://github.com/subosito/flutter-action/issues/277 | |
with: | |
channel: "stable" | |
flutter-version: ${{ env.FLUTTER_VERSION }} | |
# https://github.com/flutter/flutter/issues/155685 | |
- name: Replace engine with rustdesk custom flutter engine | |
if: false | |
run: | | |
flutter doctor -v | |
flutter precache --windows | |
Invoke-WebRequest -Uri https://github.com/rustdesk/engine/releases/download/main/windows-x64-release.zip -OutFile windows-x64-release.zip | |
Expand-Archive -Path windows-x64-release.zip -DestinationPath windows-x64-release | |
mv -Force windows-x64-release/* C:/hostedtoolcache/windows/flutter/stable-${{ env.FLUTTER_VERSION }}-x64/bin/cache/artifacts/engine/windows-x64-release/ | |
- name: Patch flutter | |
continue-on-error: true | |
shell: bash | |
run: | | |
cp .github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff $(dirname $(dirname $(which flutter))) | |
cd $(dirname $(dirname $(which flutter))) | |
[[ "3.24.5" == ${{env.FLUTTER_VERSION}} ]] && git apply flutter_3.24.4_dropdown_menu_enableFilter.diff | |
- name: Install Rust toolchain | |
uses: dtolnay/rust-toolchain@v1 | |
with: | |
toolchain: ${{ env.SCITER_RUST_VERSION }} | |
targets: ${{ matrix.job.target }} | |
components: "rustfmt" | |
- name: Report Status | |
uses: fjogeleit/http-request-action@v1 | |
with: | |
url: ${{ env.STATUS_URL }} | |
method: 'POST' | |
customHeaders: '{"Content-Type": "application/json"}' | |
data: '{"uuid": "${{ inputs.uuid }}", "status": "15% complete"}' | |
- uses: Swatinem/rust-cache@v2 | |
with: | |
prefix-key: ${{ matrix.job.os }} | |
- name: Report Status | |
uses: fjogeleit/http-request-action@v1 | |
with: | |
url: ${{ env.STATUS_URL }} | |
method: 'POST' | |
customHeaders: '{"Content-Type": "application/json"}' | |
data: '{"uuid": "${{ inputs.uuid }}", "status": "20% complete"}' | |
- name: Setup vcpkg with Github Actions binary cache | |
uses: lukka/run-vcpkg@v11 | |
with: | |
vcpkgDirectory: C:\vcpkg | |
vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }} | |
doNotCache: false | |
- name: Install vcpkg dependencies | |
env: | |
VCPKG_DEFAULT_HOST_TRIPLET: ${{ matrix.job.vcpkg-triplet }} | |
run: | | |
if ! $VCPKG_ROOT/vcpkg \ | |
install \ | |
--triplet ${{ matrix.job.vcpkg-triplet }} \ | |
--x-install-root="$VCPKG_ROOT/installed"; then | |
find "${VCPKG_ROOT}/" -name "*.log" | while read -r _1; do | |
echo "$_1:" | |
echo "======" | |
cat "$_1" | |
echo "======" | |
echo "" | |
done | |
exit 1 | |
fi | |
head -n 100 "${VCPKG_ROOT}/buildtrees/ffmpeg/build-${{ matrix.job.vcpkg-triplet }}-rel-out.log" || true | |
shell: bash | |
- name: icon stuff | |
if: ${{ inputs.iconlink != 'false' }} | |
continue-on-error: true | |
shell: bash | |
run: | | |
mv ./res/icon.ico ./res/icon.ico.bak | |
mv ./res/icon.png ./res/icon.png.bak | |
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak | |
#echo "${{ inputs.iconbase64 }}" | base64 -d > ./res/icon.png | |
- name: magick stuff | |
if: ${{ inputs.iconlink != 'false' }} | |
continue-on-error: true | |
run: | | |
Invoke-WebRequest -Uri ${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}"&"uuid=${{ fromJson(inputs.iconlink).uuid }} -OutFile ./res/icon.png | |
mv ./res/32x32.png ./res/32x32.png.bak | |
mv ./res/64x64.png ./res/64x64.png.bak | |
mv ./res/128x128.png ./res/128x128.png.bak | |
mv ./res/128x128@2x.png ./res/128x128@2x.png.bak | |
magick ./res/icon.png -define icon:auto-resize=256,64,48,32,16 ./res/icon.ico | |
cp ./res/icon.ico ./res/tray-icon.ico | |
magick ./res/icon.png -resize 32x32 ./res/32x32.png | |
magick ./res/icon.png -resize 64x64 ./res/64x64.png | |
magick ./res/icon.png -resize 128x128 ./res/128x128.png | |
magick ./res/128x128.png -resize 200% ./res/128x128@2x.png | |
- name: ui.rs icon | |
if: ${{ inputs.iconlink != 'false' }} | |
continue-on-error: true | |
shell: bash | |
run: | | |
cp ./src/ui.rs ./src/ui.rs.bak | |
b64=$(base64 < ./res/icon.png) | |
sed -i -e 's|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|$(echo "$b64")|' ./src/ui.rs | |
b64="" | |
- name: fix connection delay | |
continue-on-error: true | |
if: ${{ fromJson(inputs.extras).delayFix == 'true' }} | |
shell: bash | |
run: | | |
sed -i -e '/if !key.is_empty() && !token.is_empty() {/,/}/d' ./src/client.rs | |
- name: add cycle monitors to toolbar | |
continue-on-error: true | |
if: fromJson(inputs.extras).cycleMonitor == 'true' | |
run: | | |
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff -OutFile cycle_monitor.diff | |
git apply cycle_monitor.diff | |
- name: use X for offline display instead of orange circle | |
continue-on-error: true | |
if: fromJson(inputs.extras).xOffline == 'true' | |
run: | | |
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff -OutFile xoffline.diff | |
git apply xoffline.diff | |
- name: hide-cm | |
continue-on-error: true | |
if: fromJson(inputs.extras).hidecm == 'true' | |
run: | | |
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff -OutFile hidecm.diff | |
git apply hidecm.diff | |
- name: run as admin | |
continue-on-error: true | |
if: ${{ fromJson(inputs.extras).runasadmin == 'true' }} | |
shell: bash | |
run: | | |
echo "SET_TARGET_PROPERTIES(\${BINARY_NAME} PROPERTIES LINK_FLAGS \"/MANIFESTUAC:\\\"level='requireAdministrator' uiAccess='false'\\\" /SUBSYSTEM:WINDOWS\")" >> ./flutter/windows/runner/CMakeLists.txt | |
sed -i '/administrator/d' res/manifest.xml | |
- name: Report Status | |
uses: fjogeleit/http-request-action@v1 | |
with: | |
url: ${{ env.STATUS_URL }} | |
method: 'POST' | |
customHeaders: '{"Content-Type": "application/json"}' | |
data: '{"uuid": "${{ inputs.uuid }}", "status": "25% complete"}' | |
- name: replace flutter icons | |
if: ${{ inputs.iconlink != 'false' }} | |
continue-on-error: true | |
run: | | |
cd ./flutter | |
flutter pub upgrade win32 | |
flutter pub get | |
flutter pub run flutter_launcher_icons | |
cd .. | |
- name: Report Status | |
uses: fjogeleit/http-request-action@v1 | |
with: | |
url: ${{ env.STATUS_URL }} | |
method: 'POST' | |
customHeaders: '{"Content-Type": "application/json"}' | |
data: '{"uuid": "${{ inputs.uuid }}", "status": "50% complete, this step takes about 5 minutes, be patient."}' | |
- name: Build rustdesk | |
run: | | |
Invoke-WebRequest -Uri https://github.com/rustdesk-org/rdev/releases/download/usbmmidd_v2/usbmmidd_v2.zip -OutFile usbmmidd_v2.zip | |
Expand-Archive usbmmidd_v2.zip -DestinationPath . -Force | |
python3 .\build.py --portable --hwcodec --flutter --vram --skip-portable-pack | |
Remove-Item -Path usbmmidd_v2\Win32 -Recurse | |
Remove-Item -Path "usbmmidd_v2\deviceinstaller64.exe", "usbmmidd_v2\deviceinstaller.exe", "usbmmidd_v2\usbmmidd.bat" | |
mv ./flutter/build/windows/x64/runner/Release ./rustdesk | |
mv -Force .\usbmmidd_v2 ./rustdesk | |
- name: icon stuff | |
if: ${{ inputs.iconlink != 'false' }} | |
continue-on-error: true | |
run: | | |
mv ./rustdesk/data/flutter_assets/assets/icon.svg ./rustdesk/data/flutter_assets/assets/icon.svg.bak | |
magick ./res/icon.png ./rustdesk/data/flutter_assets/assets/icon.svg | |
- name: logo stuff | |
if: ${{ inputs.logolink != 'false' }} | |
continue-on-error: true | |
run: | | |
Invoke-WebRequest -Uri ${{ fromJson(inputs.logolink).url }}/get_png?filename=${{ fromJson(inputs.logolink).file }}"&"uuid=${{ fromJson(inputs.logolink).uuid }} -OutFile ./rustdesk/data/flutter_assets/assets/logo.png | |
- name: find Runner.res | |
# Windows: find Runner.res (compiled from ./flutter/windows/runner/Runner.rc), copy to ./Runner.res | |
# Runner.rc does not contain actual version, but Runner.res does | |
continue-on-error: true | |
shell: bash | |
run: | | |
runner_res=$(find . -name "Runner.res"); | |
if [ "$runner_res" == "" ]; then | |
echo "Runner.res: not found"; | |
else | |
echo "Runner.res: $runner_res"; | |
cp $runner_res ./libs/portable/Runner.res; | |
echo "list ./libs/portable/Runner.res"; | |
ls -l ./libs/portable/Runner.res; | |
fi | |
- name: Download RustDeskTempTopMostWindow artifacts | |
uses: actions/download-artifact@master | |
if: env.UPLOAD_ARTIFACT == 'true' | |
with: | |
name: topmostwindow-artifacts | |
path: "./rustdesk" | |
- name: Upload unsigned | |
if: env.UPLOAD_ARTIFACT == 'true' | |
uses: actions/upload-artifact@master | |
with: | |
name: rustdesk-unsigned-windows-${{ matrix.job.arch }} | |
path: rustdesk | |
# - name: Sign rustdesk files | |
# if: env.UPLOAD_ARTIFACT == 'true' && env.SIGN_BASE_URL != '' | |
# shell: bash | |
# run: | | |
# pip3 install requests argparse | |
# BASE_URL=${{ secrets.SIGN_BASE_URL }} SECRET_KEY=${{ secrets.SIGN_SECRET_KEY }} python3 res/job.py sign_files ./rustdesk/ | |
- name: Report Status | |
uses: fjogeleit/http-request-action@v1 | |
with: | |
url: ${{ env.STATUS_URL }} | |
method: 'POST' | |
customHeaders: '{"Content-Type": "application/json"}' | |
data: '{"uuid": "${{ inputs.uuid }}", "status": "70% complete, this step takes about 5 minutes, be patient."}' | |
- name: Sign rustdesk files | |
uses: GermanBluefox/code-sign-action@v7 | |
if: env.UPLOAD_ARTIFACT == 'true' | |
with: | |
certificate: '${{ secrets.WINDOWS_PFX_BASE64 }}' | |
password: '${{ secrets.WINDOWS_PFX_PASSWORD }}' | |
certificatesha1: '${{ secrets.WINDOWS_PFX_SHA1_THUMBPRINT }}' | |
# certificatename: '${{ secrets.CERTNAME }}' | |
folder: './rustdesk/' | |
recursive: true | |
- name: Create custom.txt file | |
shell: bash | |
run: | | |
echo -n "${{ env.CUSTOM }}" | cat > ./rustdesk/custom.txt | |
- name: Build self-extracted executable | |
shell: bash | |
if: env.UPLOAD_ARTIFACT == 'true' | |
run: | | |
mv "./rustdesk/rustdesk.exe" "./rustdesk/${{ inputs.appname }}.exe" || echo "rustdesk.exe" | |
sed -i '/dpiAware/d' res/manifest.xml | |
pushd ./libs/portable | |
pip3 install -r requirements.txt | |
python3 ./generate.py -f ../../rustdesk/ -o . -e "../../rustdesk/${{ inputs.appname }}.exe" | |
popd | |
mkdir -p ./SignOutput | |
mv ./target/release/rustdesk-portable-packer.exe "./SignOutput/rustdesk.exe" | |
# - name: Add MSBuild to PATH | |
# uses: microsoft/setup-msbuild@v2 | |
# - name: Build msi | |
# if: env.UPLOAD_ARTIFACT == 'true' | |
# run: | | |
# pushd ./res/msi | |
# python preprocess.py --arp -d ../../rustdesk | |
# nuget restore msi.sln | |
# msbuild msi.sln -p:Configuration=Release -p:Platform=x64 /p:TargetVersion=Windows10 | |
# cp ./Package/bin/x64/Release/en-us/Package.msi ../../SignOutput/rustdesk-latest.msi | |
# mv ./Package/bin/x64/Release/en-us/Package.msi ../../SignOutput/rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.msi | |
# sha256sum ../../SignOutput/rustdesk-*.msi | |
# - name: Sign rustdesk self-extracted file | |
# if: env.UPLOAD_ARTIFACT == 'true' && env.SIGN_BASE_URL != '' | |
# shell: bash | |
# run: | | |
# BASE_URL=${{ secrets.SIGN_BASE_URL }} SECRET_KEY=${{ secrets.SIGN_SECRET_KEY }} python3 res/job.py sign_files ./SignOutput | |
- name: Report Status | |
uses: fjogeleit/http-request-action@v1 | |
with: | |
url: ${{ env.STATUS_URL }} | |
method: 'POST' | |
customHeaders: '{"Content-Type": "application/json"}' | |
data: '{"uuid": "${{ inputs.uuid }}", "status": "85% complete"}' | |
- name: Sign rustdesk self-extracted file | |
uses: GermanBluefox/code-sign-action@v7 | |
if: env.UPLOAD_ARTIFACT == 'true' | |
with: | |
certificate: '${{ secrets.WINDOWS_PFX_BASE64 }}' | |
password: '${{ secrets.WINDOWS_PFX_PASSWORD }}' | |
certificatesha1: '${{ secrets.WINDOWS_PFX_SHA1_THUMBPRINT }}' | |
# certificatename: '${{ secrets.WINDOWS_PFX_NAME }}' | |
folder: './SignOutput' | |
recursive: false | |
# - name: Publish Release | |
# uses: softprops/action-gh-release@v1 | |
# if: env.UPLOAD_ARTIFACT == 'true' | |
# with: | |
# prerelease: true | |
# tag_name: ${{ env.TAG_NAME }} | |
# files: | | |
# ./SignOutput/rustdesk-*.msi | |
# ./SignOutput/rustdesk-*.exe | |
- name: rename rustdesk.exe to filename.exe | |
run: | | |
mv ./SignOutput/rustdesk.exe "./SignOutput/${{ inputs.filename }}.exe" || echo "rustdesk" | |
# - name: Upload to FTP | |
# if: ${{ fromJson(inputs.extras).rdgen == 'true' }} | |
# uses: SamKirkland/FTP-Deploy-Action@v4.3.5 | |
# with: | |
# server: ${{ secrets.GEN_FTP_SERVER }} | |
# username: ${{ secrets.GEN_FTP_USER }} | |
# password: ${{ secrets.GEN_FTP_PASSWORD }} | |
# local-dir: ./SignOutput/ | |
# server-dir: /root/rdgen/exe/${{ env.UUIDFOLDER }}/ | |
- name: send file to rdgen server | |
if: ${{ fromJson(inputs.extras).rdgen == 'true' }} | |
shell: bash | |
run: | | |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./SignOutput/${{ inputs.filename }}.exe" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client | |
- name: send file to api server | |
if: ${{ fromJson(inputs.extras).rdgen == 'false' }} | |
shell: bash | |
run: | | |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./SignOutput/${{ inputs.filename }}.exe" ${{ inputs.apiServer }}/api/save_custom_client | |
- name: Report Status | |
uses: fjogeleit/http-request-action@v1 | |
with: | |
url: ${{ env.STATUS_URL }} | |
method: 'POST' | |
customHeaders: '{"Content-Type": "application/json"}' | |
data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}' | |
- name: failed | |
if: failure() | |
uses: fjogeleit/http-request-action@v1 | |
with: | |
url: ${{ env.STATUS_URL }} | |
method: 'POST' | |
customHeaders: '{"Content-Type": "application/json"}' | |
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation failed, try again"}' | |
- name: failed | |
if: cancelled() | |
uses: fjogeleit/http-request-action@v1 | |
with: | |
url: ${{ env.STATUS_URL }} | |
method: 'POST' | |
customHeaders: '{"Content-Type": "application/json"}' | |
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}' |