Skip to content
This repository was archived by the owner on Sep 2, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 8 additions & 60 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,69 +142,17 @@ jobs:
- name: Verify Docker access
shell: powershell -NoProfile -ExecutionPolicy Bypass -Command ". '{0}'"
run: |
$ErrorActionPreference = "Continue"
$serviceNames = @('docker', 'com.docker.service')
$dockerDesktopStarted = $false
$desktopPaths = @(
"$env:ProgramFiles\Docker\Docker\Docker Desktop.exe",
"${env:ProgramFiles(x86)}\Docker\Docker\Docker Desktop.exe"
)

for ($attempt = 1; $attempt -le 6; $attempt++) {
Write-Host "Checking Docker access, attempt $attempt/6..."

docker version
if ($LASTEXITCODE -eq 0) {
docker ps
if ($LASTEXITCODE -eq 0) {
Write-Host "Docker daemon ready"
exit 0
}
}

foreach ($serviceName in $serviceNames) {
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if ($null -ne $service -and $service.Status -ne "Running") {
Write-Host "Starting Docker service: $serviceName"
try {
Start-Service -Name $serviceName -ErrorAction Stop
} catch {
Write-Host "Docker service start failed for ${serviceName}: $($_.Exception.Message)"
}
} elseif ($null -ne $service) {
Write-Host "Docker service ${serviceName} status: $($service.Status)"
}
}

if (-not $dockerDesktopStarted) {
foreach ($desktopPath in $desktopPaths) {
if ($desktopPath -and (Test-Path $desktopPath)) {
Write-Host "Starting Docker Desktop: $desktopPath"
$runnerTrackingId = $env:RUNNER_TRACKING_ID
try {
# Keep Docker Desktop alive after the self-hosted runner cleans up this job.
$env:RUNNER_TRACKING_ID = ""
Start-Process -FilePath $desktopPath -WindowStyle Minimized
$dockerDesktopStarted = $true
break
} catch {
Write-Host "Docker Desktop start failed: $($_.Exception.Message)"
} finally {
$env:RUNNER_TRACKING_ID = $runnerTrackingId
}
}
}
}

if ($attempt -lt 6) {
Start-Sleep -Seconds (10 * $attempt)
}
docker version
if ($LASTEXITCODE -ne 0) {
Write-Host "当前 Runner 未提供可用的 Docker Engine;请先完成 Runner 预配置"
exit $LASTEXITCODE
}

Write-Host "Docker daemon did not become ready"
docker version
docker ps
exit 1
if ($LASTEXITCODE -ne 0) {
Write-Host "当前 Runner 无权访问 Docker Engine;请先修复 Runner 权限"
exit $LASTEXITCODE
}

- name: Test and build Docker image
timeout-minutes: 15
Expand Down
29 changes: 15 additions & 14 deletions test/test_ci_cd_permission_boundary.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ def test_release_workflow_only_runs_for_master(self) -> None:
self.assertEqual(publish_job.count("name: Publish master images on Windows runner"), 1)
self.assertNotIn("name: Build on Windows runner", publish_job)

def test_windows_publish_recovers_docker_daemon_before_build(self) -> None:
def test_windows_publish_requires_preconfigured_docker_engine(self) -> None:
publish_job = self.release_document["jobs"]["publish"]
verify_step = workflow_step(publish_job, "Verify Docker access")
script = verify_step["run"]
Expand All @@ -374,19 +374,20 @@ def test_windows_publish_recovers_docker_daemon_before_build(self) -> None:
verify_step["shell"],
'powershell -NoProfile -ExecutionPolicy Bypass -Command ". \'{0}\'"',
)
self.assertIn("for ($attempt = 1; $attempt -le 6; $attempt++)", script)
self.assertIn("$serviceNames = @('docker', 'com.docker.service')", script)
self.assertIn("Start-Service -Name $serviceName", script)
self.assertIn("Docker Desktop.exe", script)
self.assertIn("Start-Process -FilePath $desktopPath", script)
self.assertIn('$env:RUNNER_TRACKING_ID = ""', script)
self.assertLess(
script.index('$env:RUNNER_TRACKING_ID = ""'),
script.index("Start-Process -FilePath $desktopPath"),
)
self.assertIn("Start-Sleep -Seconds (10 * $attempt)", script)
self.assertIn("Docker daemon ready", script)
self.assertIn("Docker daemon did not become ready", script)
self.assertEqual(script.count("docker version"), 1)
self.assertEqual(script.count("docker ps"), 1)
self.assertIn("if ($LASTEXITCODE -ne 0)", script)
self.assertIn("exit $LASTEXITCODE", script)

for forbidden_command in (
"Docker Desktop.exe",
"Start-Process",
"Start-Service",
"RUNNER_TRACKING_ID",
"Start-Sleep",
):
with self.subTest(forbidden_command=forbidden_command):
self.assertNotIn(forbidden_command, script)

def test_release_runs_are_never_cancelled_mid_deployment(self) -> None:
self.assertRegex(
Expand Down