ci(windows): make provision.ps1 self-sufficient (dedicated user, parser-bug fix); refresh stale workflow comments
build-windows / build-windows-x64 (push) Successful in 1h20m4s
build-windows / build-windows-x64 (push) Successful in 1h20m4s
This commit is contained in:
@@ -87,9 +87,10 @@ jobs:
|
||||
- name: Ensure Rust toolchain configured for runner user
|
||||
shell: pwsh
|
||||
run: |
|
||||
# provision.ps1 ran rustup as an admin user; act_runner runs as LocalSystem
|
||||
# which has its own (empty) $RUSTUP_HOME. Bootstrap the default toolchain
|
||||
# for LocalSystem on first run -- subsequent runs are no-ops.
|
||||
# provision.ps1 installs rust machine-wide (CARGO_HOME=C:\cargo,
|
||||
# RUSTUP_HOME=C:\rustup) so this is normally a no-op verification.
|
||||
# Kept as a guardrail in case the runner was provisioned with an
|
||||
# older script or by hand.
|
||||
rustup --version
|
||||
rustup toolchain install $env:RUST_VERSION --profile minimal --component rustfmt
|
||||
if ($LASTEXITCODE -ne 0) { throw "rustup toolchain install failed ($LASTEXITCODE)" }
|
||||
@@ -102,9 +103,9 @@ jobs:
|
||||
- name: Install flutter_rust_bridge codegen tools
|
||||
shell: pwsh
|
||||
run: |
|
||||
# Pin the install destination with --root so we don't have to guess at
|
||||
# the runner's $USERPROFILE (act_runner runs as LocalSystem on this host,
|
||||
# which makes $USERPROFILE a non-obvious system path).
|
||||
# Pin the install destination with --root so the resulting binaries land
|
||||
# in a deterministic, machine-wide path regardless of which user the
|
||||
# runner service is configured to run as.
|
||||
$tools = 'C:\cargo-tools'
|
||||
New-Item -ItemType Directory -Force -Path "$tools\bin" | Out-Null
|
||||
|
||||
@@ -257,14 +258,13 @@ jobs:
|
||||
fi
|
||||
fi
|
||||
|
||||
# The monolithic `python build.py` invocation that the upstream GitHub
|
||||
# workflow uses runs cargo and `flutter build windows` back-to-back. On this
|
||||
# self-hosted runner, *something* during the ~14min cargo build wipes out
|
||||
# flutter/windows, which then makes the subsequent flutter build fail with
|
||||
# "source directory does not exist" -- even though the diagnostic step
|
||||
# immediately above confirms the dir is fully present at that moment.
|
||||
# Splitting the build into discrete steps lets us restore flutter/windows
|
||||
# right before flutter needs it, after cargo has finished.
|
||||
# The upstream GitHub workflow runs `python build.py` which chains cargo +
|
||||
# `flutter build windows` in one step. We split that here so we can:
|
||||
# - get a checkpoint between cargo and flutter (~14 min apart)
|
||||
# - restore flutter/windows from git index if anything has clobbered it
|
||||
# (early in our self-hosted bring-up, flutter/windows occasionally
|
||||
# vanished during the cargo phase under LocalSystem; the restore is
|
||||
# defensive and a no-op once the runner is on a normal user)
|
||||
|
||||
- name: Cargo build (virtual_display dylib + main lib)
|
||||
shell: pwsh
|
||||
@@ -282,10 +282,9 @@ jobs:
|
||||
throw "target\release\librustdesk.dll missing after cargo build"
|
||||
}
|
||||
|
||||
# Restore + build are intentionally one step. flutter/windows has been
|
||||
# observed to disappear between steps on this runner (cause unidentified --
|
||||
# likely Windows Defender quarantine, possibly act_runner workspace handling).
|
||||
# Keeping them atomic eliminates any window of opportunity for that to happen.
|
||||
# Restore + build are intentionally one step. Closes any potential window
|
||||
# for flutter/windows to vanish between a separate restore step and the
|
||||
# build, regardless of root cause.
|
||||
- name: Flutter build windows (with last-second restore)
|
||||
shell: pwsh
|
||||
run: |
|
||||
|
||||
@@ -1,26 +1,40 @@
|
||||
# Provisions a Windows Server 2022 host as a Gitea Actions runner for RustDesk
|
||||
# desktop builds (flutter x64 + sciter x86). Idempotent: safe to re-run.
|
||||
# Provisions a Windows host (Windows 10/11 or Server 2019+) as a Gitea Actions
|
||||
# runner for RustDesk desktop builds. Idempotent: safe to re-run.
|
||||
#
|
||||
# Versions are pinned to .github/workflows/flutter-build.yml. Bump them there
|
||||
# and here together.
|
||||
# Versions are pinned to .gitea/workflows/build-windows.yml. Bump them there and
|
||||
# here together.
|
||||
#
|
||||
# Usage (Administrator PowerShell):
|
||||
# Set-ExecutionPolicy -Scope Process Bypass -Force
|
||||
# .\provision.ps1 -GiteaUrl https://gitea.example.com -RunnerToken <token>
|
||||
#
|
||||
# By default the runner service is created under a dedicated local user
|
||||
# (`gitea-runner`) -- LocalSystem has been observed to break flutter pub get,
|
||||
# symlink creation, and git's "dubious ownership" check on this codebase. To
|
||||
# opt out, pass `-ServiceAccount LocalSystem` (not recommended).
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)] [string] $GiteaUrl,
|
||||
[Parameter(Mandatory = $true)] [string] $RunnerToken,
|
||||
[string] $RunnerName = "$env:COMPUTERNAME-rustdesk",
|
||||
[string] $RunnerLabels = "windows-10,self-hosted,X64",
|
||||
[string] $RunnerVersion = "0.2.11"
|
||||
[string] $RunnerName = "$env:COMPUTERNAME-rustdesk",
|
||||
[string] $RunnerLabels = "windows-10,self-hosted,X64",
|
||||
[string] $RunnerVersion = "0.2.11",
|
||||
[string] $ServiceAccount = "gitea-runner",
|
||||
[SecureString] $ServiceAccountPassword
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
# --- pinned versions (mirror flutter-build.yml env block) ---
|
||||
# Must run elevated -- nearly every step writes Machine env, HKLM, or service config.
|
||||
$me = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
if (-not (New-Object Security.Principal.WindowsPrincipal $me).IsInRole(
|
||||
[Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
||||
throw 'Run this script in an elevated (Administrator) PowerShell session.'
|
||||
}
|
||||
|
||||
# --- pinned versions (mirror .gitea/workflows/build-windows.yml env block) ---
|
||||
$RUST_VERSION = '1.75.0'
|
||||
$RUST_NIGHTLY = 'nightly-2023-10-13'
|
||||
$LLVM_VERSION = '15.0.6'
|
||||
@@ -30,15 +44,18 @@ $VCPKG_COMMIT = '120deac3062162151622ca4860575a33844ba10b'
|
||||
$ToolsRoot = 'C:\tools'
|
||||
New-Item -ItemType Directory -Force -Path $ToolsRoot | Out-Null
|
||||
|
||||
# Exact-segment-match version of PATH augmentation. Substring matching would
|
||||
# falsely find C:\bin when C:\binaries is on PATH.
|
||||
function Add-MachinePath([string]$Dir) {
|
||||
$cur = [Environment]::GetEnvironmentVariable('Path', 'Machine')
|
||||
if ($cur -notlike "*$Dir*") {
|
||||
$segments = $cur -split ';' | Where-Object { $_ }
|
||||
if ($segments -notcontains $Dir) {
|
||||
[Environment]::SetEnvironmentVariable('Path', "$cur;$Dir", 'Machine')
|
||||
}
|
||||
if ($env:Path -notlike "*$Dir*") { $env:Path = "$env:Path;$Dir" }
|
||||
if (($env:Path -split ';') -notcontains $Dir) { $env:Path = "$env:Path;$Dir" }
|
||||
}
|
||||
|
||||
# --- 1. Chocolatey (used for git, python, nuget, 7zip) ---
|
||||
# --- 1. Chocolatey (used for git, python, nuget, 7zip, node, dotnet, ...) ---
|
||||
if (-not (Get-Command choco -ErrorAction SilentlyContinue)) {
|
||||
Write-Host '==> Installing Chocolatey'
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force
|
||||
@@ -47,14 +64,14 @@ if (-not (Get-Command choco -ErrorAction SilentlyContinue)) {
|
||||
}
|
||||
|
||||
Write-Host '==> Installing base packages'
|
||||
# nodejs-lts: act_runner needs node to execute JavaScript actions.
|
||||
# nodejs-lts: act_runner spawns Node to execute JavaScript actions.
|
||||
# powershell-core: workflows use `shell: pwsh` (PS 7), not the OS's PS 5.1.
|
||||
# dotnet-sdk: required for WiX 4 SDK-style projects (.wixproj) used by the MSI build.
|
||||
# dotnet-sdk: WiX 4 SDK-style projects (.wixproj) need it for the MSI build.
|
||||
choco install -y --no-progress `
|
||||
git python311 nuget.commandline 7zip cmake ninja `
|
||||
nodejs-lts powershell-core dotnet-sdk
|
||||
Add-MachinePath 'C:\Program Files\Git\cmd'
|
||||
Add-MachinePath 'C:\Program Files\Git\bin' # bash.exe + posix tools (sed, find, etc.)
|
||||
Add-MachinePath 'C:\Program Files\Git\bin' # bash.exe + posix tools (sed, find, ...)
|
||||
Add-MachinePath 'C:\Python311'
|
||||
Add-MachinePath 'C:\Python311\Scripts'
|
||||
Add-MachinePath 'C:\Program Files\nodejs'
|
||||
@@ -62,13 +79,17 @@ Add-MachinePath 'C:\Program Files\PowerShell\7'
|
||||
Add-MachinePath 'C:\Program Files\dotnet'
|
||||
|
||||
# --- 2. Visual Studio 2022 Build Tools (MSVC v143 + Win10 SDK) ---
|
||||
$vsInstaller = "$env:ProgramFiles(x86)\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
$vsPresent = (Test-Path $vsInstaller) -and ((& $vsInstaller -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath) -ne $null)
|
||||
# Use [Environment]::GetEnvironmentVariable to avoid the PowerShell parser quirk
|
||||
# that mis-tokenises `$env:ProgramFiles(x86)` as `$env:ProgramFiles` + `(x86)`.
|
||||
$pfx86 = [Environment]::GetEnvironmentVariable('ProgramFiles(x86)')
|
||||
$vsInstaller = Join-Path $pfx86 'Microsoft Visual Studio\Installer\vswhere.exe'
|
||||
$vsPresent = (Test-Path $vsInstaller) -and `
|
||||
((& $vsInstaller -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath) -ne $null)
|
||||
if (-not $vsPresent) {
|
||||
Write-Host '==> Installing VS 2022 Build Tools (this takes a while)'
|
||||
$vsBootstrapper = "$env:TEMP\vs_buildtools.exe"
|
||||
Invoke-WebRequest -Uri 'https://aka.ms/vs/17/release/vs_buildtools.exe' -OutFile $vsBootstrapper
|
||||
$args = @(
|
||||
$vsArgs = @(
|
||||
'--quiet','--wait','--norestart','--nocache',
|
||||
'--add','Microsoft.VisualStudio.Workload.VCTools',
|
||||
'--add','Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
|
||||
@@ -77,14 +98,14 @@ if (-not $vsPresent) {
|
||||
'--add','Microsoft.VisualStudio.Component.VC.CMake.Project',
|
||||
'--includeRecommended'
|
||||
)
|
||||
$p = Start-Process -FilePath $vsBootstrapper -ArgumentList $args -Wait -PassThru
|
||||
$p = Start-Process -FilePath $vsBootstrapper -ArgumentList $vsArgs -Wait -PassThru
|
||||
if ($p.ExitCode -notin 0,3010) { throw "VS Build Tools installer exit $($p.ExitCode)" }
|
||||
}
|
||||
|
||||
# --- 3. Rust (stable 1.75 + nightly-2023-10-13 with i686 target) ---
|
||||
# Install machine-wide so the act_runner service (LocalSystem) and any admin user
|
||||
# share the same toolchain registry. Without this, rustup state lives in the
|
||||
# installing user's profile and LocalSystem ends up with no default toolchain.
|
||||
# --- 3. Rust (stable + nightly with i686 target) ---
|
||||
# Install machine-wide so any user (including the dedicated runner account)
|
||||
# shares one toolchain registry. Without this, rustup state lives in the
|
||||
# installing user's profile and the service user has no default toolchain.
|
||||
$rustupHome = 'C:\rustup'
|
||||
$cargoHome = 'C:\cargo'
|
||||
[Environment]::SetEnvironmentVariable('RUSTUP_HOME', $rustupHome, 'Machine')
|
||||
@@ -104,7 +125,7 @@ rustup toolchain install $RUST_NIGHTLY --profile minimal --component rustfmt
|
||||
rustup target add --toolchain $RUST_NIGHTLY i686-pc-windows-msvc
|
||||
rustup default $RUST_VERSION
|
||||
|
||||
# --- 4. LLVM/Clang 15.0.6 (matches KyleMayes/install-llvm-action) ---
|
||||
# --- 4. LLVM/Clang (matches KyleMayes/install-llvm-action layout) ---
|
||||
$llvmDir = "$ToolsRoot\llvm-$LLVM_VERSION"
|
||||
if (-not (Test-Path "$llvmDir\bin\clang.exe")) {
|
||||
Write-Host "==> Installing LLVM $LLVM_VERSION"
|
||||
@@ -115,7 +136,7 @@ if (-not (Test-Path "$llvmDir\bin\clang.exe")) {
|
||||
[Environment]::SetEnvironmentVariable('LIBCLANG_PATH', "$llvmDir\bin", 'Machine')
|
||||
Add-MachinePath "$llvmDir\bin"
|
||||
|
||||
# --- 5. Flutter 3.24.5 (stable channel, with windows precache) ---
|
||||
# --- 5. Flutter (stable channel, with windows precache) ---
|
||||
$flutterDir = "$ToolsRoot\flutter"
|
||||
if (-not (Test-Path "$flutterDir\bin\flutter.bat")) {
|
||||
Write-Host "==> Installing Flutter $FLUTTER_VERSION"
|
||||
@@ -141,7 +162,102 @@ Pop-Location
|
||||
[Environment]::SetEnvironmentVariable('VCPKG_ROOT', $vcpkgDir, 'Machine')
|
||||
Add-MachinePath $vcpkgDir
|
||||
|
||||
# --- 7. Gitea act_runner ---
|
||||
# --- 7. CI prerequisites that aren't tools, but environmental switches ---
|
||||
|
||||
# git's "dubious ownership" check (>= 2.35.2) refuses to operate on a repo whose
|
||||
# .git directory is owned by a different user than the one running git. The
|
||||
# Flutter SDK at C:\tools\flutter is provisioned by this script as Administrator
|
||||
# but the runner service runs as a non-admin user. Trust everything system-wide.
|
||||
git config --system --add safe.directory '*' 2>$null
|
||||
|
||||
# Flutter on Windows needs SeCreateSymbolicLinkPrivilege to build plugins.
|
||||
# Enable Developer Mode (registry) AND grant the privilege via Local Security
|
||||
# Policy to the built-in "Users" group (SID S-1-5-32-545). Either alone has been
|
||||
# observed to not take effect until logon-token refresh; doing both is
|
||||
# belt-and-suspenders. The privilege only reaches a long-running service after
|
||||
# a reboot or a fresh service-token issuance.
|
||||
$devKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock'
|
||||
if (-not (Test-Path $devKey)) { New-Item -Path $devKey -Force | Out-Null }
|
||||
New-ItemProperty -Path $devKey -Name 'AllowDevelopmentWithoutDevLicense' `
|
||||
-PropertyType DWORD -Value 1 -Force | Out-Null
|
||||
|
||||
$secCfg = "$env:TEMP\sec-symlink.cfg"
|
||||
secedit /export /cfg $secCfg | Out-Null
|
||||
$secContent = Get-Content $secCfg -Raw
|
||||
if ($secContent -match 'SeCreateSymbolicLinkPrivilege\s*=\s*([^\r\n]*)') {
|
||||
$cur = $matches[1]
|
||||
if ($cur -notmatch '\*S-1-5-32-545') {
|
||||
$secContent = $secContent -replace `
|
||||
'(SeCreateSymbolicLinkPrivilege\s*=\s*)([^\r\n]*)', `
|
||||
'$1$2,*S-1-5-32-545'
|
||||
}
|
||||
} else {
|
||||
$secContent = $secContent -replace `
|
||||
'(\[Privilege Rights\][\r\n]+)', `
|
||||
"`$1SeCreateSymbolicLinkPrivilege = *S-1-5-32-545`r`n"
|
||||
}
|
||||
$secContent | Set-Content $secCfg
|
||||
secedit /configure /db "$env:TEMP\sec-symlink.sdb" /cfg $secCfg /areas USER_RIGHTS /quiet
|
||||
Remove-Item $secCfg, "$env:TEMP\sec-symlink.sdb" -ErrorAction SilentlyContinue
|
||||
|
||||
# --- 8. Dedicated runner user ---
|
||||
# Running as LocalSystem causes a cascade of issues:
|
||||
# - $USERPROFILE = C:\Windows\System32\config\systemprofile, which Flutter,
|
||||
# dart pub, and other POSIX-leaning tools mis-handle.
|
||||
# - cargo install lands binaries in that systemprofile path -> not on PATH.
|
||||
# - flutter/windows occasionally vanishes during long cargo builds.
|
||||
# A normal local user fixes all of these.
|
||||
if ($ServiceAccount -ne 'LocalSystem') {
|
||||
if (-not (Get-LocalUser -Name $ServiceAccount -ErrorAction SilentlyContinue)) {
|
||||
if (-not $ServiceAccountPassword) {
|
||||
# Generate a 32-byte random password using the OS RNG. Encoded as
|
||||
# base64 (alphanumeric + +/) and trimmed of padding -- meets local
|
||||
# password complexity without needing System.Web (which is missing
|
||||
# on Server Core).
|
||||
$bytes = New-Object byte[] 24
|
||||
[System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
|
||||
$plain = ([Convert]::ToBase64String($bytes)).TrimEnd('=') + 'A1!'
|
||||
$ServiceAccountPassword = ConvertTo-SecureString $plain -AsPlainText -Force
|
||||
Remove-Variable plain, bytes
|
||||
}
|
||||
Write-Host "==> Creating local user '$ServiceAccount'"
|
||||
New-LocalUser -Name $ServiceAccount -Password $ServiceAccountPassword `
|
||||
-PasswordNeverExpires -AccountNeverExpires `
|
||||
-Description 'Gitea Actions runner service account' | Out-Null
|
||||
Add-LocalGroupMember -Group 'Users' -Member $ServiceAccount
|
||||
}
|
||||
|
||||
# Grant "Log on as a service" via secedit (no PS native cmdlet for this).
|
||||
$sid = (Get-LocalUser $ServiceAccount).SID.Value
|
||||
$svcCfg = "$env:TEMP\sec-svc.cfg"
|
||||
secedit /export /cfg $svcCfg | Out-Null
|
||||
$svcContent = Get-Content $svcCfg -Raw
|
||||
if ($svcContent -match "SeServiceLogonRight\s*=\s*([^\r\n]*)") {
|
||||
if ($matches[1] -notmatch [regex]::Escape($sid)) {
|
||||
$svcContent = $svcContent -replace `
|
||||
'(SeServiceLogonRight\s*=\s*)([^\r\n]*)', `
|
||||
"`$1`$2,*$sid"
|
||||
}
|
||||
} else {
|
||||
$svcContent = $svcContent -replace `
|
||||
'(\[Privilege Rights\][\r\n]+)', `
|
||||
"`$1SeServiceLogonRight = *$sid`r`n"
|
||||
}
|
||||
$svcContent | Set-Content $svcCfg
|
||||
secedit /configure /db "$env:TEMP\sec-svc.sdb" /cfg $svcCfg /areas USER_RIGHTS /quiet
|
||||
Remove-Item $svcCfg, "$env:TEMP\sec-svc.sdb" -ErrorAction SilentlyContinue
|
||||
|
||||
# Ensure the user can read/write everything it needs for builds.
|
||||
foreach ($p in @('C:\actions-runner','C:\cargo','C:\cargo-tools','C:\vcpkg','C:\vcpkg-cache')) {
|
||||
New-Item -ItemType Directory -Force -Path $p | Out-Null
|
||||
icacls $p /grant "${ServiceAccount}:(OI)(CI)F" /T 2>$null | Out-Null
|
||||
}
|
||||
foreach ($p in @('C:\rustup','C:\tools')) {
|
||||
if (Test-Path $p) { icacls $p /grant "${ServiceAccount}:(OI)(CI)RX" /T 2>$null | Out-Null }
|
||||
}
|
||||
}
|
||||
|
||||
# --- 9. Gitea act_runner ---
|
||||
$runnerDir = 'C:\actions-runner'
|
||||
New-Item -ItemType Directory -Force -Path $runnerDir | Out-Null
|
||||
$runnerExe = "$runnerDir\act_runner.exe"
|
||||
@@ -159,35 +275,50 @@ if (-not (Test-Path "$runnerDir\.runner")) {
|
||||
--name $RunnerName `
|
||||
--labels $RunnerLabels
|
||||
}
|
||||
if (-not (Get-Service -Name 'gitea-act-runner' -ErrorAction SilentlyContinue)) {
|
||||
|
||||
# Reconfigure the service every run so re-running with a different
|
||||
# -ServiceAccount actually takes effect.
|
||||
$svc = Get-Service -Name 'gitea-act-runner' -ErrorAction SilentlyContinue
|
||||
if ($svc) {
|
||||
if ($svc.Status -eq 'Running') { Stop-Service gitea-act-runner }
|
||||
} else {
|
||||
Write-Host '==> Installing runner as Windows service'
|
||||
# nssm is the cleanest way to host a console exe as a service on Windows.
|
||||
choco install -y --no-progress nssm
|
||||
nssm install gitea-act-runner $runnerExe daemon
|
||||
nssm set gitea-act-runner AppDirectory $runnerDir
|
||||
nssm set gitea-act-runner Start SERVICE_AUTO_START
|
||||
nssm set gitea-act-runner AppStdout "$runnerDir\runner.log"
|
||||
nssm set gitea-act-runner AppStderr "$runnerDir\runner.log"
|
||||
nssm install gitea-act-runner $runnerExe daemon | Out-Null
|
||||
}
|
||||
nssm set gitea-act-runner AppDirectory $runnerDir | Out-Null
|
||||
nssm set gitea-act-runner Start SERVICE_AUTO_START | Out-Null
|
||||
nssm set gitea-act-runner AppStdout "$runnerDir\runner.log" | Out-Null
|
||||
nssm set gitea-act-runner AppStderr "$runnerDir\runner.log" | Out-Null
|
||||
|
||||
if ($ServiceAccount -eq 'LocalSystem') {
|
||||
nssm set gitea-act-runner ObjectName 'LocalSystem' | Out-Null
|
||||
} else {
|
||||
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($ServiceAccountPassword)
|
||||
try {
|
||||
$plain = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($bstr)
|
||||
nssm set gitea-act-runner ObjectName ".\$ServiceAccount" $plain | Out-Null
|
||||
} finally {
|
||||
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
|
||||
Remove-Variable plain -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
# Start may fail before reboot if the new SeServiceLogonRight hasn't reached
|
||||
# SCM yet -- that's expected; the service will start cleanly after reboot.
|
||||
try {
|
||||
Start-Service gitea-act-runner
|
||||
} catch {
|
||||
Write-Warning "Could not start gitea-act-runner now ($($_.Exception.Message)). It will start on reboot."
|
||||
}
|
||||
Start-Service gitea-act-runner
|
||||
Pop-Location
|
||||
|
||||
# --- 8. CI prerequisites that aren't tools, but are environmental switches ---
|
||||
|
||||
# git's "dubious ownership" check (>= 2.35.2) refuses to operate on a repo whose
|
||||
# .git directory is owned by a different user than the one running git.
|
||||
# C:\tools\flutter is provisioned by this script (running as admin) but the
|
||||
# runner service runs as a non-admin user. Trust everything system-wide.
|
||||
git config --system --add safe.directory '*' 2>$null
|
||||
|
||||
# Flutter on Windows needs SeCreateSymbolicLinkPrivilege to build plugins.
|
||||
# Enabling Developer Mode grants this to all non-admin users without per-user
|
||||
# secedit gymnastics.
|
||||
$devKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock'
|
||||
if (-not (Test-Path $devKey)) { New-Item -Path $devKey -Force | Out-Null }
|
||||
New-ItemProperty -Path $devKey -Name 'AllowDevelopmentWithoutDevLicense' `
|
||||
-PropertyType DWORD -Value 1 -Force | Out-Null
|
||||
|
||||
Write-Host ''
|
||||
Write-Host '==> Done. Reboot recommended so PATH/env changes take effect for the runner service.'
|
||||
Write-Host ' After reboot, verify the runner shows up green in Gitea > Site Admin > Actions > Runners.'
|
||||
Write-Host '==> Done.'
|
||||
Write-Host ' A reboot is REQUIRED before the first build run, so:'
|
||||
Write-Host ' - the runner service inherits the new SeCreateSymbolicLinkPrivilege token'
|
||||
Write-Host ' - all PATH/env changes propagate to the SCM-launched service'
|
||||
Write-Host ' After reboot, verify the runner shows up in Gitea > Site Admin > Actions > Runners.'
|
||||
if ($ServiceAccount -eq 'LocalSystem') {
|
||||
Write-Warning 'Service is running as LocalSystem. RustDesk builds have been observed to fail in this configuration (Flutter pub get, symlinks, dubious ownership). Re-run with -ServiceAccount gitea-runner to switch.'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user