diff --git a/.gitea/actions/decrypt-secrets/action.yml b/.gitea/actions/decrypt-secrets/action.yml index 330f0bb..8043ada 100644 --- a/.gitea/actions/decrypt-secrets/action.yml +++ b/.gitea/actions/decrypt-secrets/action.yml @@ -15,7 +15,12 @@ runs: - name: install python deps shell: bash run: | - pip install pyzipper + # Ubuntu 24.04 enforces PEP 668 (externally-managed-environment) and + # minimal macOS runners ship no pip by default: try the system installer + # first, then a --user install, finally bootstrap pip via ensurepip. + python3 -m pip install --break-system-packages -q pyzipper 2>/dev/null \ + || python3 -m pip install -q --user pyzipper 2>/dev/null \ + || { python3 -m ensurepip --user && python3 -m pip install -q --user pyzipper; } - name: Decrypt and Mask shell: python env: diff --git a/.gitea/workflows/generator-android.yml b/.gitea/workflows/generator-android.yml index 60c4cf4..0666a05 100644 --- a/.gitea/workflows/generator-android.yml +++ b/.gitea/workflows/generator-android.yml @@ -105,6 +105,8 @@ jobs: method: 'POST' customHeaders: '{"Content-Type": "application/json"}' data: '{"uuid": "${{ env.uuid }}"}' + timeout: '15000' + retry: '3' - name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@main @@ -195,17 +197,17 @@ jobs: continue-on-error: true run: | cd $(dirname $(dirname $(which flutter))) - [[ "3.24.5" == ${{env.ANDROID_FLUTTER_VERSION}} ]] && git apply ${{ github.workspace }}/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff - + [[ "3.24.5" == ${{env.ANDROID_FLUTTER_VERSION}} ]] && git apply ${{ github.workspace }}/.rdgen-src/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff - - uses: nttld/setup-ndk@v1 + + - uses: nttld/setup-ndk@afb4c9964b521afb97c864b7d40b11e6911bd410 # v1 pinned to node20 runtime id: setup-ndk with: ndk-version: ${{ env.NDK_VERSION }} add-to-path: true - name: Setup vcpkg with Github Actions binary cache - uses: lukka/run-vcpkg@v11 + uses: lukka/run-vcpkg@1737e223b9c3f4fb07a7cf1cfa123cc243fcc0dd # v11 pinned to node20 runtime with: vcpkgDirectory: /opt/artifacts/vcpkg vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }} @@ -599,7 +601,7 @@ jobs: - uses: r0adkll/sign-android-release@v1 name: Sign app APK continue-on-error: true - if: env.ANDROID_SIGNING_KEY != null + if: env.ANDROID_SIGNING_KEY != '' id: sign-rustdesk with: releaseDirectory: ./signed-apk @@ -639,7 +641,7 @@ jobs: retry_wait_seconds: 15 shell: bash command: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./signed-apk/${{ env.filename }}-${{ matrix.job.arch }}.apk" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./signed-apk/${{ env.filename }}-${{ matrix.job.arch }}.apk" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client - name: send file to api server if: ${{ env.rdgen == 'false' }} @@ -650,10 +652,11 @@ jobs: retry_wait_seconds: 15 shell: bash command: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./signed-apk/${{ env.filename }}-${{ matrix.job.arch }}.apk" ${{ env.apiServer }}/api/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./signed-apk/${{ env.filename }}-${{ matrix.job.arch }}.apk" ${{ env.apiServer }}/api/save_custom_client deploy: needs: [build-rustdesk-android] + if: always() runs-on: ubuntu-latest steps: - name: Checkout Repository @@ -679,6 +682,8 @@ jobs: method: 'POST' customHeaders: '{"Content-Type": "application/json"}' data: '{"uuid": "${{ env.uuid }}"}' + timeout: '15000' + retry: '3' - name: Set rdgen value if: ${{ env.rdgen == 'true' }} @@ -690,6 +695,30 @@ jobs: run: | echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $GITHUB_ENV + - name: Report build status + if: always() + shell: bash + env: + BUILD_RESULT: ${{ needs.build-rustdesk-android.result }} + run: | + # Single aggregated callback for the whole matrix: per-leg callbacks + # could flip a failed run back to success when legs finish out of order. + case "$BUILD_RESULT" in + success) STATUS=success ;; + cancelled) STATUS=cancelled ;; + *) STATUS=failure ;; + esac + if [ -z "${{ env.uuid }}" ] || [ -z "$STATUS_URL" ]; then + echo "::warning::uuid or STATUS_URL missing, skip status callback" + exit 0 + fi + echo "Reporting status=$STATUS for uuid=${{ env.uuid }}" + curl --fail --silent --show-error \ + --connect-timeout 10 --max-time 30 --retry 3 --retry-delay 5 \ + -X POST -H "Content-Type: application/json" \ + -d "{\"uuid\":\"${{ env.uuid }}\",\"status\":\"$STATUS\"}" \ + "$STATUS_URL" || echo "::warning::status callback failed" + - uses: geekyeggo/delete-artifact@v4 continue-on-error: true with: diff --git a/.gitea/workflows/generator-linux.yml b/.gitea/workflows/generator-linux.yml index 42d3560..789511f 100644 --- a/.gitea/workflows/generator-linux.yml +++ b/.gitea/workflows/generator-linux.yml @@ -65,7 +65,7 @@ jobs: arch: x86_64, target: x86_64-unknown-linux-gnu, distro: ubuntu18.04, - on: ubuntu-22.04, + on: ubuntu-24.04, deb_arch: amd64, vcpkg-triplet: x64-linux, } @@ -73,7 +73,7 @@ jobs: arch: aarch64, target: aarch64-unknown-linux-gnu, distro: ubuntu18.04, - on: ubuntu-22.04-arm, + on: ubuntu-24.04-arm, deb_arch: arm64, vcpkg-triplet: arm64-linux, } @@ -172,7 +172,7 @@ jobs: - name: Setup vcpkg with Github Actions binary cache if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true' - uses: lukka/run-vcpkg@v11 + uses: lukka/run-vcpkg@1737e223b9c3f4fb07a7cf1cfa123cc243fcc0dd # v11 pinned to node20 runtime with: vcpkgDirectory: /opt/artifacts/vcpkg vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }} @@ -402,7 +402,9 @@ jobs: with: arch: ${{ matrix.job.arch }} distro: ${{ matrix.job.distro }} - githubToken: ${{ github.token }} + # Gitea Actions tokens cannot authenticate against ghcr.io; leave it + # empty so run-on-arch pulls the image anonymously. + githubToken: '' setup: | ls -l "${PWD}" ls -l /opt/artifacts/vcpkg/installed @@ -533,7 +535,9 @@ jobs: pushd /opt/flutter ;; esac - git apply ${{ github.workspace }}/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff + # Inside the run-on-arch container the host workspace is mounted + # at /workspace, and rdgen itself lives in .rdgen-src. + git apply /workspace/.rdgen-src/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff popd fi @@ -686,10 +690,10 @@ jobs: retry_wait_seconds: 15 shell: bash command: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.deb" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.rpm" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.deb" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.rpm" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true - name: send file to api server if: ${{ env.rdgen == 'false' }} @@ -700,10 +704,10 @@ jobs: retry_wait_seconds: 15 shell: bash command: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.deb" ${{ env.apiServer }}/api/save_custom_client - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.rpm" ${{ env.apiServer }}/api/save_custom_client - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm" ${{ env.apiServer }}/api/save_custom_client - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" ${{ env.apiServer }}/api/save_custom_client || true + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.deb" ${{ env.apiServer }}/api/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.rpm" ${{ env.apiServer }}/api/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm" ${{ env.apiServer }}/api/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" ${{ env.apiServer }}/api/save_custom_client || true - name: Upload deb uses: actions/upload-artifact@v4 @@ -715,7 +719,7 @@ jobs: build-rustdesk-linux-drm: needs: [generate-bridge-linux, setup] name: build rustdesk linux drm x86_64 - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 # Only rustdesk's master branch carries the drm/libdrmtap support this job # drives: build.py at tag 1.4.9 has neither build_libdrmtap_so nor # assert_staged_binary_is_drm, so a versioned build dies at @@ -824,7 +828,7 @@ jobs: path: ./ - name: Setup vcpkg with Github Actions binary cache - uses: lukka/run-vcpkg@v11 + uses: lukka/run-vcpkg@1737e223b9c3f4fb07a7cf1cfa123cc243fcc0dd # v11 pinned to node20 runtime with: vcpkgDirectory: /opt/artifacts/vcpkg vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }} @@ -1072,7 +1076,9 @@ jobs: with: arch: x86_64 distro: ubuntu18.04 - githubToken: ${{ github.token }} + # Gitea Actions tokens cannot authenticate against ghcr.io; leave it + # empty so run-on-arch pulls the image anonymously. + githubToken: '' setup: | ls -l "${PWD}" ls -l /opt/artifacts/vcpkg/installed @@ -1165,7 +1171,9 @@ jobs: if [[ "3.24.5" == ${{ env.FLUTTER_VERSION }} ]]; then pushd /opt/flutter - git apply ${{ github.workspace }}/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff + # Inside the run-on-arch container the host workspace is mounted + # at /workspace, and rdgen itself lives in .rdgen-src. + git apply /workspace/.rdgen-src/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff popd fi @@ -1237,7 +1245,7 @@ jobs: retry_wait_seconds: 15 shell: bash command: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-unattended-wayland-x86_64.deb" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-unattended-wayland-x86_64.deb" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client - name: send file to api server if: ${{ env.rdgen == 'false' && env.DRM_SUPPORTED == 'true' }} @@ -1248,7 +1256,7 @@ jobs: retry_wait_seconds: 15 shell: bash command: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-unattended-wayland-x86_64.deb" ${{ env.apiServer }}/api/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-unattended-wayland-x86_64.deb" ${{ env.apiServer }}/api/save_custom_client - name: Upload deb uses: actions/upload-artifact@v4 @@ -1260,7 +1268,7 @@ jobs: build-appimage: name: Build appimage ${{ matrix.job.target }} needs: [build-rustdesk-linux] - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -1388,7 +1396,7 @@ jobs: retry_wait_seconds: 15 shell: bash command: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./appimage/${{ env.filename }}-${{ matrix.job.arch }}.AppImage" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./appimage/${{ env.filename }}-${{ matrix.job.arch }}.AppImage" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client - name: send file to api server if: ${{ env.rdgen == 'false' }} @@ -1399,7 +1407,7 @@ jobs: retry_wait_seconds: 15 shell: bash command: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./appimage/${{ env.filename }}-${{ matrix.job.arch }}.AppImage" ${{ env.apiServer }}/api/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./appimage/${{ env.filename }}-${{ matrix.job.arch }}.AppImage" ${{ env.apiServer }}/api/save_custom_client build-flatpak: name: Build flatpak ${{ matrix.job.target }}${{ matrix.job.suffix }} @@ -1413,7 +1421,7 @@ jobs: - { target: x86_64-unknown-linux-gnu, distro: ubuntu22.04, - on: ubuntu-22.04, + on: ubuntu-24.04, arch: x86_64, suffix: "", } @@ -1421,7 +1429,7 @@ jobs: target: aarch64-unknown-linux-gnu, # try out newer flatpak since error of "error: Nothing matches org.freedesktop.Platform in remote flathub" distro: ubuntu22.04, - on: ubuntu-22.04-arm, + on: ubuntu-24.04-arm, arch: aarch64, suffix: "", } @@ -1473,7 +1481,9 @@ jobs: with: arch: ${{ matrix.job.arch }} distro: ${{ matrix.job.distro }} - githubToken: ${{ github.token }} + # Gitea Actions tokens cannot authenticate against ghcr.io; leave it + # empty so run-on-arch pulls the image anonymously. + githubToken: '' setup: | ls -l "${PWD}" dockerRunArgs: | @@ -1529,7 +1539,7 @@ jobs: retry_wait_seconds: 15 shell: bash command: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./flatpak/${{ env.filename }}-${{ matrix.job.arch }}.flatpak" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./flatpak/${{ env.filename }}-${{ matrix.job.arch }}.flatpak" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client - name: send file to api server if: ${{ env.rdgen == 'false' }} @@ -1540,7 +1550,7 @@ jobs: retry_wait_seconds: 15 shell: bash command: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./flatpak/${{ env.filename }}-${{ matrix.job.arch }}.flatpak" ${{ env.apiServer }}/api/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./flatpak/${{ env.filename }}-${{ matrix.job.arch }}.flatpak" ${{ env.apiServer }}/api/save_custom_client deploy: needs: [build-rustdesk-linux,build-flatpak,build-appimage] @@ -1570,6 +1580,8 @@ jobs: method: 'POST' customHeaders: '{"Content-Type": "application/json"}' data: '{"uuid": "${{ env.uuid }}"}' + timeout: '15000' + retry: '3' - name: Set rdgen value if: ${{ env.rdgen == 'true' }} @@ -1581,6 +1593,33 @@ jobs: run: | echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $GITHUB_ENV + - name: Report build status + if: always() + shell: bash + env: + BUILD_RESULTS: "${{ needs.build-rustdesk-linux.result }}/${{ needs.build-flatpak.result }}/${{ needs.build-appimage.result }}" + run: | + # Aggregate the deb/rpm, flatpak and appimage jobs. The optional drm + # job is not a gating artifact and is intentionally excluded. + if [ "$BUILD_RESULTS" = "success/success/success" ]; then + STATUS=success + elif echo "$BUILD_RESULTS" | grep -q "cancelled"; then + STATUS=cancelled + else + # failure / skipped (e.g. setup failed and all builds were skipped) + STATUS=failure + fi + if [ -z "${{ env.uuid }}" ] || [ -z "$STATUS_URL" ]; then + echo "::warning::uuid or STATUS_URL missing, skip status callback" + exit 0 + fi + echo "Reporting status=$STATUS ($BUILD_RESULTS) for uuid=${{ env.uuid }}" + curl --fail --silent --show-error \ + --connect-timeout 10 --max-time 30 --retry 3 --retry-delay 5 \ + -X POST -H "Content-Type: application/json" \ + -d "{\"uuid\":\"${{ env.uuid }}\",\"status\":\"$STATUS\"}" \ + "$STATUS_URL" || echo "::warning::status callback failed" + - uses: geekyeggo/delete-artifact@v4 continue-on-error: true with: diff --git a/.gitea/workflows/generator-macos.yml b/.gitea/workflows/generator-macos.yml index 321f392..159b27f 100644 --- a/.gitea/workflows/generator-macos.yml +++ b/.gitea/workflows/generator-macos.yml @@ -101,6 +101,8 @@ jobs: method: 'POST' customHeaders: '{"Content-Type": "application/json"}' data: '{"uuid": "${{ env.uuid }}"}' + timeout: '15000' + retry: '3' - name: Checkout source code @@ -294,7 +296,7 @@ jobs: continue-on-error: true run: | cd $(dirname $(dirname $(which flutter))) - [[ "3.24.5" == ${{env.FLUTTER_VERSION}} ]] && git apply ${{ github.workspace }}/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff + [[ "3.24.5" == ${{env.FLUTTER_VERSION}} ]] && git apply ${{ github.workspace }}/.rdgen-src/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff - name: Workaround for flutter issue shell: bash @@ -500,7 +502,7 @@ jobs: path: ./ - name: Setup vcpkg with Github Actions binary cache - uses: lukka/run-vcpkg@v11 + uses: lukka/run-vcpkg@1737e223b9c3f4fb07a7cf1cfa123cc243fcc0dd # v11 pinned to node20 runtime with: vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }} doNotCache: false @@ -550,7 +552,7 @@ jobs: ls -l "$APP/Contents/MacOS/custom_.txt" - name: Install rcodesign tool - if: env.MACOS_P12_BASE64 != null + if: env.MACOS_P12_BASE64 != '' shell: bash run: | pushd /tmp @@ -584,7 +586,11 @@ jobs: continue-on-error: false shell: bash run: | - ASSETS_DIR="build/macos/Build/Products/Release/RustDesk.app/Contents/Frameworks/App.framework/Versions/Current/Resources/flutter_assets/assets" + # build.py renames the bundle to the custom app name: locate *.app + # dynamically instead of assuming RustDesk.app still exists. + APP=$(find ./flutter/build/macos/Build/Products/Release -maxdepth 1 -name "*.app" | head -n 1) + echo "App bundle: $APP" + ASSETS_DIR="$APP/Contents/Frameworks/App.framework/Versions/Current/Resources/flutter_assets/assets" mkdir -p "$ASSETS_DIR" if [ -f "$ASSETS_DIR/icon.svg" ]; then mv "$ASSETS_DIR/icon.svg" "$ASSETS_DIR/icon.svg.bak" @@ -600,7 +606,11 @@ jobs: continue-on-error: false shell: bash run: | - ASSETS_DIR="build/macos/Build/Products/Release/RustDesk.app/Contents/Frameworks/App.framework/Versions/Current/Resources/flutter_assets/assets" + # build.py renames the bundle to the custom app name: locate *.app + # dynamically instead of assuming RustDesk.app still exists. + APP=$(find ./flutter/build/macos/Build/Products/Release -maxdepth 1 -name "*.app" | head -n 1) + echo "App bundle: $APP" + ASSETS_DIR="$APP/Contents/Frameworks/App.framework/Versions/Current/Resources/flutter_assets/assets" mkdir -p "$ASSETS_DIR" curl -k -L --tlsv1.2 --proto =https --ssl-reqd \ -H "User-Agent: Mozilla/5.0" \ @@ -696,7 +706,7 @@ jobs: - name: Create DMG run: | - cd /Users/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/flutter/build/macos/Build/Products/Release + cd $GITHUB_WORKSPACE/flutter/build/macos/Build/Products/Release # Print directory contents for debugging echo "Directory contents:" ls -la @@ -745,7 +755,7 @@ jobs: if: ${{ env.rdgen == 'true' }} shell: bash run: | - curl -i -X POST \ + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 \ -H "Content-Type: multipart/form-data" \ -H "Authorization: Bearer ${{ env.token }}" \ -F "file=@$GITHUB_WORKSPACE/${{ env.filename }}-${{ matrix.job.arch }}.dmg" \ @@ -757,7 +767,7 @@ jobs: if: ${{ env.rdgen == 'false' }} shell: bash run: | - curl -i -X POST \ + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 \ -H "Content-Type: multipart/form-data" \ -H "Authorization: Bearer ${{ env.token }}" \ -F "file=@$GITHUB_WORKSPACE/${{ env.filename }}-${{ matrix.job.arch }}.dmg" \ @@ -769,6 +779,48 @@ jobs: continue-on-error: true if: always() steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + path: .rdgen-src + + - uses: actions/download-artifact@v4 + with: + name: encrypted-secrets-zip + + - name: Load Secrets + uses: ./.gitea/actions/decrypt-secrets + with: + zip_password: ${{ secrets.ZIP_PASSWORD }} + + - name: Report build status + if: always() + shell: bash + env: + BUILD_RESULT: ${{ needs.build-for-macos.result }} + run: | + # Single aggregated callback for the x86_64/aarch64 matrix. + case "$BUILD_RESULT" in + success) STATUS=success ;; + cancelled) STATUS=cancelled ;; + *) STATUS=failure ;; + esac + if [ "${{ env.rdgen }}" = "false" ]; then + STATUS_URL="${{ env.apiServer }}/api/updategh" + else + STATUS_URL="${{ secrets.GENURL }}/updategh" + fi + if [ -z "${{ env.uuid }}" ]; then + echo "::warning::uuid missing, skip status callback" + exit 0 + fi + echo "Reporting status=$STATUS for uuid=${{ env.uuid }}" + curl --fail --silent --show-error \ + --connect-timeout 10 --max-time 30 --retry 3 --retry-delay 5 \ + -X POST -H "Content-Type: application/json" \ + -d "{\"uuid\":\"${{ env.uuid }}\",\"status\":\"$STATUS\"}" \ + "$STATUS_URL" || echo "::warning::status callback failed" + - name: Delete secrets artifact uses: geekyeggo/delete-artifact@v4 with: diff --git a/.gitea/workflows/generator-windows-x86.yml b/.gitea/workflows/generator-windows-x86.yml index e2034ef..a2300dd 100644 --- a/.gitea/workflows/generator-windows-x86.yml +++ b/.gitea/workflows/generator-windows-x86.yml @@ -28,7 +28,7 @@ env: # 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;files,D:\vcpkg-cache,readwrite" + VCPKG_BINARY_SOURCES: 'clear;files,D:\vcpkg-cache,readwrite' # vcpkg version: 2025.08.27 # If we change the `VCPKG COMMIT_ID`, please remember: # 1. Call `$VCPKG_ROOT/vcpkg x-update-baseline` to update the baseline in `vcpkg.json`. @@ -56,6 +56,11 @@ jobs: name: ${{ matrix.job.target }} (${{ matrix.job.os }}) needs: setup runs-on: ${{ matrix.job.os }} + # Gitea act defaults to bash on Windows hosts; most unmarked steps here are + # PowerShell. Requires PowerShell 7 (pwsh) installed on the self-hosted runner. + defaults: + run: + shell: pwsh # Temporarily disable this action due to additional test is needed. # if: false strategy: @@ -95,6 +100,8 @@ jobs: method: 'POST' customHeaders: '{"Content-Type": "application/json"}' data: '{"uuid": "${{ env.uuid }}"}' + timeout: '15000' + retry: '3' - name: Set rdgen value @@ -277,7 +284,7 @@ jobs: prefix-key: ${{ matrix.job.os }}-sciter - name: Setup vcpkg with Github Actions binary cache - uses: lukka/run-vcpkg@v11 + uses: lukka/run-vcpkg@1737e223b9c3f4fb07a7cf1cfa123cc243fcc0dd # v11 pinned to node20 runtime with: vcpkgDirectory: C:\vcpkg vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }} @@ -422,9 +429,9 @@ jobs: cargo build --target ${{ matrix.job.target }} --features inline,vram,hwcodec --release --bins mkdir -p ./Release mv ./target/${{ matrix.job.target }}/release/rustdesk.exe ./Release/rustdesk.exe - curl -LJ -o ./Release/sciter.dll https://github.com/c-smile/sciter-sdk/raw/master/bin.win/x32/sciter.dll + curl --fail -LJ --connect-timeout 30 --max-time 300 --retry 3 --retry-delay 5 -o ./Release/sciter.dll https://github.com/c-smile/sciter-sdk/raw/master/bin.win/x32/sciter.dll echo "output_folder=./Release" >> $GITHUB_OUTPUT - curl -LJ -o ./usbmmidd_v2.zip https://github.com/rustdesk-org/rdev/releases/download/usbmmidd_v2/usbmmidd_v2.zip + curl --fail -LJ --connect-timeout 30 --max-time 300 --retry 3 --retry-delay 5 -o ./usbmmidd_v2.zip https://github.com/rustdesk-org/rdev/releases/download/usbmmidd_v2/usbmmidd_v2.zip unzip usbmmidd_v2.zip # Do not remove x64 files, because the user may run the 32bit version on a 64bit system. # Do not remove ./usbmmidd_v2/deviceinstaller64.exe, as x86 exe cannot install and uninstall drivers when running on x64, @@ -534,13 +541,13 @@ jobs: if: ${{ env.rdgen == 'true' }} shell: bash run: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.exe" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.exe" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client - name: send file to api server if: ${{ env.rdgen == 'false' }} shell: bash run: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.exe" ${{ env.apiServer }}/api/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.exe" ${{ env.apiServer }}/api/save_custom_client cleanup: needs: [build-for-windows-sciter] @@ -548,6 +555,48 @@ jobs: continue-on-error: true if: always() steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + path: .rdgen-src + + - uses: actions/download-artifact@v4 + with: + name: encrypted-secrets-zip + + - name: Load Secrets + uses: ./.gitea/actions/decrypt-secrets + with: + zip_password: ${{ secrets.ZIP_PASSWORD }} + + - name: Report build status + if: always() + shell: bash + env: + BUILD_RESULT: ${{ needs.build-for-windows-sciter.result }} + run: | + # Single aggregated callback (the build job may be skipped/cancelled). + case "$BUILD_RESULT" in + success) STATUS=success ;; + cancelled) STATUS=cancelled ;; + *) STATUS=failure ;; + esac + if [ "${{ env.rdgen }}" = "false" ]; then + STATUS_URL="${{ env.apiServer }}/api/updategh" + else + STATUS_URL="${{ secrets.GENURL }}/updategh" + fi + if [ -z "${{ env.uuid }}" ]; then + echo "::warning::uuid missing, skip status callback" + exit 0 + fi + echo "Reporting status=$STATUS for uuid=${{ env.uuid }}" + curl --fail --silent --show-error \ + --connect-timeout 10 --max-time 30 --retry 3 --retry-delay 5 \ + -X POST -H "Content-Type: application/json" \ + -d "{\"uuid\":\"${{ env.uuid }}\",\"status\":\"$STATUS\"}" \ + "$STATUS_URL" || echo "::warning::status callback failed" + - name: Delete secrets artifact uses: geekyeggo/delete-artifact@v4 with: diff --git a/.gitea/workflows/generator-windows.yml b/.gitea/workflows/generator-windows.yml index ccd5955..49a2225 100644 --- a/.gitea/workflows/generator-windows.yml +++ b/.gitea/workflows/generator-windows.yml @@ -28,7 +28,7 @@ env: # 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;files,D:\vcpkg-cache,readwrite" + VCPKG_BINARY_SOURCES: 'clear;files,D:\vcpkg-cache,readwrite' # vcpkg version: 2024.07.12 VCPKG_COMMIT_ID: "${{ inputs.version == 'master' && '9e593bb18ea69cc5095e012465dcd675a822ed0d' || '120deac3062162151622ca4860575a33844ba10b' }}" ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" @@ -70,6 +70,11 @@ jobs: name: Build Windows needs: [build-RustDeskTempTopMostWindow, generate-bridge, setup] runs-on: ${{ matrix.job.os }} + # Gitea act defaults to bash on Windows hosts; most unmarked steps here are + # PowerShell. Requires PowerShell 7 (pwsh) installed on the self-hosted runner. + defaults: + run: + shell: pwsh strategy: fail-fast: false matrix: @@ -107,6 +112,8 @@ jobs: method: 'POST' customHeaders: '{"Content-Type": "application/json"}' data: '{"uuid": "${{ env.uuid }}"}' + timeout: '15000' + retry: '3' - name: Set rdgen value @@ -385,7 +392,7 @@ jobs: - name: Patch flutter shell: bash run: | - cp .github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff $(dirname $(dirname $(which flutter))) + cp .rdgen-src/.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 @@ -401,7 +408,7 @@ jobs: prefix-key: ${{ matrix.job.os }} - name: Setup vcpkg with Github Actions binary cache - uses: lukka/run-vcpkg@v11 + uses: lukka/run-vcpkg@1737e223b9c3f4fb07a7cf1cfa123cc243fcc0dd # v11 pinned to node20 runtime with: vcpkgDirectory: C:\vcpkg vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }} @@ -723,8 +730,8 @@ jobs: retry_wait_seconds: 15 shell: bash command: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.exe" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.msi" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.exe" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.msi" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true - name: send file to api server if: ${{ env.rdgen == 'false' }} @@ -735,8 +742,8 @@ jobs: retry_wait_seconds: 15 shell: bash command: | - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.exe" ${{ env.apiServer }}/api/save_custom_client - curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.msi" ${{ env.apiServer }}/api/save_custom_client || true + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.exe" ${{ env.apiServer }}/api/save_custom_client + curl --fail -i -X POST --connect-timeout 10 --max-time 300 --retry 3 --retry-delay 5 -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.msi" ${{ env.apiServer }}/api/save_custom_client || true cleanup: needs: [build-for-windows-flutter] @@ -744,6 +751,49 @@ jobs: continue-on-error: true if: always() steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + path: .rdgen-src + + - uses: actions/download-artifact@v4 + with: + name: encrypted-secrets-zip + + - name: Load Secrets + uses: ./.gitea/actions/decrypt-secrets + with: + zip_password: ${{ secrets.ZIP_PASSWORD }} + + - name: Report build status + if: always() + shell: bash + env: + BUILD_RESULT: ${{ needs.build-for-windows-flutter.result }} + run: | + # Single aggregated callback. needs.result also covers the upstream + # reusable jobs: if third-party/bridge/setup fail the build is "skipped". + case "$BUILD_RESULT" in + success) STATUS=success ;; + cancelled) STATUS=cancelled ;; + *) STATUS=failure ;; + esac + if [ "${{ env.rdgen }}" = "false" ]; then + STATUS_URL="${{ env.apiServer }}/api/updategh" + else + STATUS_URL="${{ secrets.GENURL }}/updategh" + fi + if [ -z "${{ env.uuid }}" ]; then + echo "::warning::uuid missing, skip status callback" + exit 0 + fi + echo "Reporting status=$STATUS for uuid=${{ env.uuid }}" + curl --fail --silent --show-error \ + --connect-timeout 10 --max-time 30 --retry 3 --retry-delay 5 \ + -X POST -H "Content-Type: application/json" \ + -d "{\"uuid\":\"${{ env.uuid }}\",\"status\":\"$STATUS\"}" \ + "$STATUS_URL" || echo "::warning::status callback failed" + - name: Delete secrets artifact uses: geekyeggo/delete-artifact@v4 with: diff --git a/.gitea/workflows/sh-generator-windows.yml b/.gitea/workflows/sh-generator-windows.yml index fddcbf0..91ac383 100644 --- a/.gitea/workflows/sh-generator-windows.yml +++ b/.gitea/workflows/sh-generator-windows.yml @@ -28,7 +28,7 @@ env: # 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;files,D:\vcpkg-cache,readwrite" + VCPKG_BINARY_SOURCES: 'clear;files,D:\vcpkg-cache,readwrite' # vcpkg version: 2024.07.12 VCPKG_COMMIT_ID: "${{ inputs.version == 'master' && '9e593bb18ea69cc5095e012465dcd675a822ed0d' || '120deac3062162151622ca4860575a33844ba10b' }}" ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" diff --git a/.gitea/workflows/third-party-RustDeskTempTopMostWindow.yml b/.gitea/workflows/third-party-RustDeskTempTopMostWindow.yml index 432f724..8e58197 100644 --- a/.gitea/workflows/third-party-RustDeskTempTopMostWindow.yml +++ b/.gitea/workflows/third-party-RustDeskTempTopMostWindow.yml @@ -27,6 +27,13 @@ on: required: true type: string default: 'Windows10' + secrets: + ZIP_PASSWORD: + description: 'Password for the encrypted secrets zip' + required: true + GENURL: + description: 'rdgen platform base URL' + required: true env: project_path: WindowInjection/WindowInjection.vcxproj @@ -63,6 +70,8 @@ jobs: method: 'POST' customHeaders: '{"Content-Type": "application/json"}' data: '{"uuid": "${{ env.uuid }}"}' + timeout: '15000' + retry: '3' - name: Download the source code run: | @@ -78,7 +87,7 @@ jobs: shell: pwsh command: | cd RustDeskTempTopMostWindow && git checkout 53b548a5398624f7149a382000397993542ad796 - if ($env:privacylink_url-ne "false") { + if ($env:privacylink_url -ne "false") { Invoke-WebRequest -Uri ${{ env.privacylink_url }}/get_png?filename=${{ env.privacylink_file }}"&"uuid=${{ env.privacylink_uuid }} -OutFile privacy.png Copy-Item ../.github/patches/privacyScreen.py privacyScreen.py python privacyScreen.py diff --git a/rdgenerator/static/rdgenerator/css/app.css b/rdgenerator/static/rdgenerator/css/app.css index bf8d48c..714bf6f 100644 --- a/rdgenerator/static/rdgenerator/css/app.css +++ b/rdgenerator/static/rdgenerator/css/app.css @@ -134,6 +134,26 @@ a:hover { text-decoration: underline; } } .btn-logout:hover { border-color: var(--danger); color: var(--danger); } +/* ===== 顶部导航移动端适配:窄屏上下两行,导航单行横向滑动不折行 ===== */ +@media (max-width: 768px) { + .topbar-inner { + height: auto; + flex-direction: column; + align-items: stretch; + gap: 8px; + padding: 10px 16px; + } + .topbar nav { + flex-wrap: nowrap; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + padding-bottom: 2px; + } + .topbar nav::-webkit-scrollbar { display: none; } + .nav-link, .nav-user, .btn-logout { flex: none; } +} + /* ===== 页面容器与标题 ===== */ .page { flex: 1; diff --git a/rdgenerator/templates/base.html b/rdgenerator/templates/base.html index 4b39576..f8dfb25 100644 --- a/rdgenerator/templates/base.html +++ b/rdgenerator/templates/base.html @@ -111,6 +111,9 @@ + + + diff --git a/rdgenerator/templates/my_builds.html b/rdgenerator/templates/my_builds.html index be70287..3ea0ba2 100644 --- a/rdgenerator/templates/my_builds.html +++ b/rdgenerator/templates/my_builds.html @@ -35,7 +35,7 @@ - {% if run.status == 'success' %} 下载产物{% elif run.is_finished %}查看详情{% else %}查看进度{% endif %} + {% if run.status == 'success' %} 下载产物{% elif run.is_finished %} 查看详情{% else %} 查看进度{% endif %} {% if run.github_log_url %} diff --git a/setup.md b/setup.md index 65d0cee..6c75fda 100644 --- a/setup.md +++ b/setup.md @@ -125,11 +125,18 @@ Gitea 不提供云构建机,每个需要构建的平台都要自行注册 runn | 标签 | 用途 | 运行方式 | | --- | --- | --- | -| `ubuntu-22.04` | Linux x86_64、Android 构建 | Linux 主机 Docker 模式 | -| `ubuntu-22.04-arm` | Linux arm64、Android arm 构建 | arm64 Linux 主机 Docker 模式 | -| `windows-2022` | Windows x64/x86 构建 | Windows 主机 host 模式(真机/虚拟机) | -| `macos-14` | macOS arm64 构建 | Apple Silicon Mac host 模式 | -| `macos-15-intel` | macOS x64 构建 | Intel Mac host 模式 | +| `ubuntu-24.04` | Linux x86_64、Android(armv7/aarch64 走 NDK 交叉编译)、drm/appimage/flatpak x86_64 | Linux x86_64 主机 Docker 模式 | +| `ubuntu-24.04-arm` | Linux arm64 的 deb/flatpak 原生构建 | arm64 Linux 主机 Docker 模式(需另注册) | +| `windows-2022` | Windows x64/x86 构建 | Windows 主机 host 模式(真机/虚拟机,需另注册) | +| `macos-14` | macOS arm64 构建 | Apple Silicon Mac host 模式(需另注册) | +| `macos-15-intel` | macOS x64 构建 | Intel Mac host 模式(需另注册) | + +另外大量轻量步骤(拉取加密配置、收尾回调、artifact 清理)运行在 +`ubuntu-latest` 标签上——act_runner 默认自带的 `ubuntu-latest`/`docker`/`amd64` +标签即可承接,但必须确保有 runner 显式提供 `ubuntu-24.04` 标签,否则主构建会 +一直处于 waiting。只注册一台 x86_64 Linux runner 时 Android 与 Linux x86_64 +构建即可工作;arm64 Linux、Windows、macOS 必须各自再注册对应机器,对应任务在 +机器就绪前会排队等待。 **Linux(Docker 模式,推荐)**: @@ -143,7 +150,8 @@ docker run -d --name gitea-runner --restart always \ ``` 首次启动生成 `/data/config.yaml` 后,按需把 `labels` 改为上面的标签,例如 -`- "ubuntu-22.04:docker://ghcr.io/catthehacker/ubuntu:act-22.04"`,再重启容器。 +`- "ubuntu-24.04:docker://ghcr.io/catthehacker/ubuntu:act-24.04"`(act 官方 +镜像还有 `ubuntu:act-latest` 可挂到 `ubuntu-latest` 标签),再重启容器。 工作流把 vcpkg 二进制缓存放在容器内 `/opt/vcpkg-cache`,如需跨任务复用,可在 job 容器配置中把该路径挂为持久卷。 @@ -155,9 +163,16 @@ job 容器配置中把该路径挂为持久卷。 > (如 `https://gitea.example.com`)或宿主机映射地址(如 `http://10.0.0.10:39630`), > 改完编辑 `/data/config.yaml` 的 `runner.address` 重启即可,无需重新注册。 -**Windows(host 模式)**:在准备好构建环境的 Windows 机器上 -(Git、PowerShell、Visual Studio 2022、vcpkg 位于 `C:\vcpkg`,并预创建 -`D:\vcpkg-cache`;ImageMagick 等由工作流自动安装): +**Windows(host 模式)**:在准备好构建环境的 Windows 机器上构建。Gitea act +在 Windows 上默认 shell 是 bash,而本仓库工作流已显式把默认 shell 设为 +**PowerShell 7(pwsh)**,因此机器上必须安装: + +* **PowerShell 7+**(`pwsh` 必须在 PATH 中;仅有 Windows 自带的 5.1 不够) +* **Git for Windows**(提供 Git Bash,部分步骤显式使用 `shell: bash`) +* **Python 3**(decrypt-secrets composite action 需要,且能 `python -m pip`) +* **Visual Studio 2022**(含 C++ 桌面开发、MSVC、Windows SDK) +* **vcpkg** 固定位于 `C:\vcpkg`,并**预创建 `D:\vcpkg-cache`** 二进制缓存目录 +* **Chocolatey / NuGet**(工作流用其安装 ImageMagick、WiX 等构建依赖) ```powershell # 下载 https://gitea.com/gitea/act_runner/releases 的 act_runner.exe @@ -168,8 +183,11 @@ job 容器配置中把该路径挂为持久卷。 确认稳定后再用任务计划程序/NSSM 注册为开机服务。 **macOS(host 模式)**:使用 Apple 硬件(arm64 对应 `macos-14`,Intel 对应 -`macos-15-intel`,安装 Xcode 命令行工具),同样下载 act_runner 二进制后以 -`macos-14:host` 标签注册并 launchd 守护。 +`macos-15-intel`)。仅安装 Xcode 命令行工具不够,必须安装**完整版 Xcode** +(Flutter macOS 构建与代码签名需要),并具备 Homebrew、CocoaPods +(`sudo gem install cocoapods` 或 brew 版)、运行 runner 的用户可**免密 +sudo**。同样下载 act_runner 二进制后以 `macos-14:host` 标签注册并 launchd +守护。 ### 3. 内网网络说明 @@ -188,6 +206,10 @@ job 容器配置中把该路径挂为持久卷。 (`.rdgen-src/.github/patches/`),不依赖 raw.githubusercontent.com。 * rdgen 后台的 `GITEA_PROXY` 仅用于「服务端 → Gitea API」的调用;Gitea 通常 与 rdgen 在同一内网,留空直连即可。 +* **runner 必须能反向访问 rdgen(`GENURL`)**:每个工作流结束时(无论成功、 + 失败还是取消)都会向 `${GENURL}/updategh` 回调最终状态。收不到回调的构建 + 会在 6 小时后被服务端误判为超时,因此 `GENURL` 要填 runner 实际可达的地址, + 不能只填浏览器端能访问的地址。 ### 4. 在 rdgen 侧启用