From 7282aab4510875cd849aec2b34d1017e36779bc9 Mon Sep 17 00:00:00 2001 From: comimit775 Date: Sun, 31 May 2026 06:59:24 +0000 Subject: [PATCH] Optimize Tailscale workflows: caching, parallelization, fix dispatch URLs - Rename workflow files to match dispatch URLs (fixes broken cross-workflow chain) - Cache Tailscale MSI with actions/cache@v4 (skip ~50MB download on cache hit) - Cache pip packages (skip re-download of pyautogui, pynput, pillow) - Run pip install in parallel with Tailscale install via background process - Remove redundant --force-reinstall and pip upgrade (saves ~15-30s) - Merge 'Decide runtime' into the main install step (reduce step overhead) - Reduce STOP cooldown heartbeat frequency (5 min intervals vs 1 min) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- ...lscale (Workflow 1).yml => workflow-1.yml} | 58 +++++++++++++------ ...lscale (Workflow 2).yml => workflow-2.yml} | 45 ++++++++++---- ...(STOP & RESTART).yml => workflow-stop.yml} | 15 +++-- 3 files changed, 83 insertions(+), 35 deletions(-) rename .github/workflows/{RDP + Tailscale (Workflow 1).yml => workflow-1.yml} (68%) rename .github/workflows/{RDP + Tailscale (Workflow 2).yml => workflow-2.yml} (62%) rename .github/workflows/{RDP + Tailscale (STOP & RESTART).yml => workflow-stop.yml} (83%) diff --git a/.github/workflows/RDP + Tailscale (Workflow 1).yml b/.github/workflows/workflow-1.yml similarity index 68% rename from .github/workflows/RDP + Tailscale (Workflow 1).yml rename to .github/workflows/workflow-1.yml index 6ac5c95..6449956 100644 --- a/.github/workflows/RDP + Tailscale (Workflow 1).yml +++ b/.github/workflows/workflow-1.yml @@ -45,28 +45,57 @@ jobs: RDP_PASS: Bullet@12345 steps: - - name: Decide runtime + - name: Cache Tailscale MSI + uses: actions/cache@v4 + id: ts-cache + with: + path: ${{ runner.temp }}\tailscale.msi + key: tailscale-1.82.0-amd64 + + - name: Cache pip packages + uses: actions/cache@v4 + with: + path: ~\AppData\Local\pip\Cache + key: pip-win-pyautogui-pynput-pillow + + - name: Install Tailscale + Python (parallel) run: | + # Start pip install in background + $pipOut = "$env:TEMP\pip-out.txt" + $pipErr = "$env:TEMP\pip-err.txt" + $pipProc = Start-Process python -ArgumentList "-m","pip","install","pyautogui","pynput","pillow" ` + -NoNewWindow -PassThru -RedirectStandardOutput $pipOut -RedirectStandardError $pipErr + + # Determine runtime function Yes($v){ "$v" -match '^(?i:true|1|yes|on)$' } - $rt=if(Yes("${{ inputs.quick_test }}")){5}else{[int]"${{ inputs.runtime_minutes }}"} + $rt = if(Yes("${{ inputs.quick_test }}")){5}else{[int]"${{ inputs.runtime_minutes }}"} if($rt -gt 360){$rt=355} - "RUNTIME_MINUTES=$rt"|Out-File -Append $env:GITHUB_ENV + "RUNTIME_MINUTES=$rt" | Out-File -Append $env:GITHUB_ENV Write-Host "Runtime set to $rt minutes" - - name: Install + Configure Tailscale - run: | - $ts="$env:ProgramFiles\Tailscale\tailscale.exe" + # Install + connect Tailscale + $ts = "$env:ProgramFiles\Tailscale\tailscale.exe" if(-not(Test-Path $ts)){ - $url="https://pkgs.tailscale.com/stable/tailscale-setup-1.82.0-amd64.msi" - $dst="$env:TEMP\tailscale.msi" - Invoke-WebRequest $url -OutFile $dst + $dst = "${{ runner.temp }}\tailscale.msi" + if(-not(Test-Path $dst)){ + Invoke-WebRequest "https://pkgs.tailscale.com/stable/tailscale-setup-1.82.0-amd64.msi" -OutFile $dst + } Start-Process msiexec.exe -ArgumentList "/i","`"$dst`"","/quiet","/norestart" -Wait } & $ts up --authkey "${{ inputs.ts_authkey }}" --hostname "bullet1" --accept-dns=true - $ip=& $ts ip -4 |Select-Object -First 1 - "TAILSCALE_IP=$ip"|Out-File -Append $env:GITHUB_ENV + $ip = & $ts ip -4 | Select-Object -First 1 + "TAILSCALE_IP=$ip" | Out-File -Append $env:GITHUB_ENV Write-Host "Tailscale IPv4: $ip" + # Wait for pip install + $pipProc | Wait-Process + if($pipProc.ExitCode -ne 0){ + Get-Content $pipErr -EA SilentlyContinue + throw "pip install failed with exit code $($pipProc.ExitCode)" + } + Write-Host "Python libs installed:" + Get-Content $pipOut -EA SilentlyContinue + - name: Enable RDP run: | $u=$env:RDP_USER; $p=$env:RDP_PASS @@ -80,11 +109,6 @@ jobs: Enable-NetFirewallRule -DisplayGroup "Remote Desktop" Write-Host "RDP ready: $u / $p @ $env:TAILSCALE_IP" - - name: Install Python libs - run: | - python -m pip install --upgrade pip - python -m pip install --force-reinstall pyautogui pynput pillow - - name: Keep alive run: | $end=(Get-Date).AddMinutes([int]"${{ env.RUNTIME_MINUTES }}") @@ -110,4 +134,4 @@ jobs: $hdr=@{Authorization="Bearer $env:GH_TOKEN";Accept="application/vnd.github+json"} $body=@{ref="${{ github.ref_name }}";inputs=$payload}|ConvertTo-Json -Depth 20 Invoke-WebRequest -Method POST -Uri $url -Headers $hdr -Body $body|Out-Null - Write-Host "โžก๏ธ Workflow 2 triggered. Cycles left: $next" + Write-Host "Workflow 2 triggered. Cycles left: $next" diff --git a/.github/workflows/RDP + Tailscale (Workflow 2).yml b/.github/workflows/workflow-2.yml similarity index 62% rename from .github/workflows/RDP + Tailscale (Workflow 2).yml rename to .github/workflows/workflow-2.yml index e82f0ff..27b0e30 100644 --- a/.github/workflows/RDP + Tailscale (Workflow 2).yml +++ b/.github/workflows/workflow-2.yml @@ -29,22 +29,47 @@ jobs: RDP_PASS: Bullet@12345 steps: - - name: Setup Tailscale + RDP + - name: Cache Tailscale MSI + uses: actions/cache@v4 + id: ts-cache + with: + path: ${{ runner.temp }}\tailscale.msi + key: tailscale-1.82.0-amd64 + + - name: Cache pip packages + uses: actions/cache@v4 + with: + path: ~\AppData\Local\pip\Cache + key: pip-win-pyautogui-pynput-pillow + + - name: Setup Tailscale + Python (parallel) run: | - $ts="$env:ProgramFiles\Tailscale\tailscale.exe" + # Start pip install in background + $pipOut = "$env:TEMP\pip-out.txt" + $pipErr = "$env:TEMP\pip-err.txt" + $pipProc = Start-Process python -ArgumentList "-m","pip","install","pyautogui","pynput","pillow" ` + -NoNewWindow -PassThru -RedirectStandardOutput $pipOut -RedirectStandardError $pipErr + + # Install + connect Tailscale + $ts = "$env:ProgramFiles\Tailscale\tailscale.exe" if(-not(Test-Path $ts)){ - $url="https://pkgs.tailscale.com/stable/tailscale-setup-1.82.0-amd64.msi" - $dst="$env:TEMP\tailscale.msi" - Invoke-WebRequest $url -OutFile $dst + $dst = "${{ runner.temp }}\tailscale.msi" + if(-not(Test-Path $dst)){ + Invoke-WebRequest "https://pkgs.tailscale.com/stable/tailscale-setup-1.82.0-amd64.msi" -OutFile $dst + } Start-Process msiexec.exe -ArgumentList "/i","`"$dst`"","/quiet","/norestart" -Wait } & $ts up --authkey "${{ inputs.ts_authkey }}" --hostname "bullet2" --accept-dns=true Enable-NetFirewallRule -DisplayGroup "Remote Desktop" - - name: Install Python libs - run: | - python -m pip install --upgrade pip - python -m pip install --force-reinstall pyautogui pynput pillow + # Wait for pip install + $pipProc | Wait-Process + if($pipProc.ExitCode -ne 0){ + Get-Content $pipErr -EA SilentlyContinue + throw "pip install failed with exit code $($pipProc.ExitCode)" + } + Write-Host "Python libs installed:" + Get-Content $pipOut -EA SilentlyContinue - name: Keep alive run: | @@ -71,4 +96,4 @@ jobs: $hdr=@{Authorization="Bearer $env:GH_TOKEN";Accept="application/vnd.github+json"} $body=@{ref="${{ github.ref_name }}";inputs=$payload}|ConvertTo-Json -Depth 20 Invoke-WebRequest -Method POST -Uri $url -Headers $hdr -Body $body|Out-Null - Write-Host "๐Ÿ›‘ STOP workflow triggered (cycles left: ${{ inputs.cycles_left }})" + Write-Host "STOP workflow triggered (cycles left: ${{ inputs.cycles_left }})" diff --git a/.github/workflows/RDP + Tailscale (STOP & RESTART).yml b/.github/workflows/workflow-stop.yml similarity index 83% rename from .github/workflows/RDP + Tailscale (STOP & RESTART).yml rename to .github/workflows/workflow-stop.yml index 3b1d854..5659411 100644 --- a/.github/workflows/RDP + Tailscale (STOP & RESTART).yml +++ b/.github/workflows/workflow-stop.yml @@ -37,26 +37,25 @@ jobs: $count++ } } - Write-Host "๐Ÿงน Removed $count bullet devices from Tailscale." - }catch{Write-Host "โš ๏ธ Cleanup failed: $($_.Exception.Message)"} + Write-Host "Removed $count bullet devices from Tailscale." + }catch{Write-Host "Cleanup failed: $($_.Exception.Message)"} - name: Decide next step id: next run: | $left=[int]"${{ inputs.cycles_left }}" if($left -le 0){ - Write-Host "โœ… 5 cycles completed. Stopping permanently." + Write-Host "All 5 cycles completed. Stopping permanently." "RESTART=0"|Out-File -Append $env:GITHUB_ENV }else{ - Write-Host "โณ Waiting 20 min before restarting Workflow 1. Cycles left: $left" + Write-Host "Waiting 20 min before restarting Workflow 1. Cycles left: $left" "RESTART=1"|Out-File -Append $env:GITHUB_ENV } - name: Wait 20 minutes (if restarting) if: env.RESTART == '1' run: | - $end=(Get-Date).AddMinutes(20) - while((Get-Date) -lt $end){Write-Host ("๐Ÿ•’ Cooling down "+(Get-Date));Start-Sleep 60} + for($i=1;$i -le 4;$i++){Write-Host "Cooling down ($i/4)";Start-Sleep 300} - name: Restart Workflow 1 (if cycles remain) if: env.RESTART == '1' @@ -64,7 +63,7 @@ jobs: GH_TOKEN: ${{ github.token }} run: | $next=[int]"${{ inputs.cycles_left }}"-1 - if($next -le 0){Write-Host "โœ… Finished all cycles.";exit 0} + if($next -le 0){Write-Host "Finished all cycles.";exit 0} $payload=@{ ts_tailnet="${{ inputs.ts_tailnet }}" ts_api_key="${{ inputs.ts_api_key }}" @@ -79,4 +78,4 @@ jobs: $hdr=@{Authorization="Bearer $env:GH_TOKEN";Accept="application/vnd.github+json"} $body=@{ref="${{ github.ref_name }}";inputs=$payload}|ConvertTo-Json -Depth 20 Invoke-WebRequest -Method POST -Uri $url -Headers $hdr -Body $body|Out-Null - Write-Host "๐Ÿš€ Workflow 1 restarted (cycles left: $next)" + Write-Host "Workflow 1 restarted (cycles left: $next)"