Files
Hua.Todo/publish-linux.ps1
ShaoHua d81aa06681 refactor: 重构文档结构与环境配置,统一研发工单命名
1. 更新 .env 配置文件,替换原有云同步变量为 API 目标配置
2. 调整 publish-linux.ps1 中的文档路径,使用研发工单目录
3. 重构项目文档目录:将原 v1.2.0-tasks 迁移为研发工单-v1.2.0 目录,统一术语为"研发工单"替代"任务"
4. 更新 README.md 与各 PRD 文档的术语对照表,明确业务实体与研发工作项的区分
5. 新增多个研发工单文档,覆盖搜索、云同步、Linux 打包等模块
6. 删除旧的任务拆分文档,统一使用新的研发工单体系
2026-06-14 00:58:26 +08:00

213 lines
7.7 KiB
PowerShell
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<#
Hua.Todo Linux 发布脚本(产出 .tar.gz
目标:
- 为 Linux 提供可分发的目录产物(dotnet publish 输出)
- 在 Windows 开发机上也能交叉发布 linux-x64(便于 CI 前的本地验证)
约束:
- Avalonia Linux 入口项目需先落地(参见 docs/project/研发工单-v1.2.0/01-*
- 仅打包为 tar.gzFlatpak/AppImage 需要在 Linux 环境执行相关工具链(参见 pack/linux/ 说明)
#>
param(
[ValidateSet("linux-x64", "linux-arm64")]
[string]$RuntimeIdentifier = "linux-x64",
[string]$TargetFramework = "net10.0",
[switch]$SelfContained,
[switch]$SkipProcessStop,
[switch]$SkipRestore,
[ValidateSet("Release", "Debug")]
[string]$Configuration = "Release",
[string]$BaseIntermediateOutputPath
)
$ErrorActionPreference = "Stop"
$ScriptPath = $PSScriptRoot
$DirectoryBuildProps = Join-Path $ScriptPath "Directory.Build.props"
function Get-FirstExistingFilePath {
param(
[Parameter(Mandatory = $true)]
[string[]]$Candidates
)
foreach ($candidate in $Candidates) {
if (Test-Path $candidate) {
return $candidate
}
}
return $null
}
function Read-ProjectVersion {
param(
[Parameter(Mandatory = $true)]
[string]$ProjectFile,
[string]$DirectoryBuildProps
)
$currentVersion = "0.0.0"
# 1. Try Directory.Build.props first
if ($null -ne $DirectoryBuildProps -and (Test-Path $DirectoryBuildProps)) {
[xml]$props = Get-Content $DirectoryBuildProps -Raw
$versionNode = $props.SelectSingleNode("//Version")
if ($null -ne $versionNode -and -not [string]::IsNullOrWhiteSpace($versionNode.InnerText)) {
return $versionNode.InnerText.Trim()
}
}
# 2. Try .csproj
[xml]$csproj = Get-Content $ProjectFile -Raw
$versionNode = $csproj.SelectSingleNode("//Version")
if ($null -ne $versionNode -and -not [string]::IsNullOrWhiteSpace($versionNode.InnerText)) {
return $versionNode.InnerText.Trim()
}
$versionNode = $csproj.SelectSingleNode("//ApplicationDisplayVersion")
if ($null -ne $versionNode -and -not [string]::IsNullOrWhiteSpace($versionNode.InnerText)) {
return $versionNode.InnerText.Trim()
}
return $currentVersion
}
function Stop-ProjectProcesses {
Write-Host "Shutting down dotnet build servers..." -ForegroundColor Yellow
dotnet build-server shutdown | Out-Null
Write-Host "Checking for running processes to prevent file locks..." -ForegroundColor Yellow
# Aggressively look for anything related to the project or MSBuild/dotnet background tasks
$processesToKill = Get-Process | Where-Object {
$_.ProcessName -like "*Hua.Todo*" -or
$_.ProcessName -eq "MSBuild" -or
($_.ProcessName -eq "dotnet" -and ($_.CommandLine -like "*Hua.Todo*" -or $_.CommandLine -like "*msbuild*"))
}
if ($processesToKill) {
Write-Host "Stopping $($processesToKill.Count) running processes..." -ForegroundColor Yellow
foreach ($p in $processesToKill) {
try {
Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue
} catch {
Write-Warning "Failed to stop process $($p.ProcessName) (ID: $($p.Id))"
}
}
Start-Sleep -Seconds 2 # Give OS more time to release file handles
} else {
Write-Host "No conflicting processes found." -ForegroundColor Green
}
}
if (!$SkipProcessStop.IsPresent) {
Stop-ProjectProcesses
}
$candidateProjects = @(
(Join-Path $ScriptPath "src\Hua.Todo.Avalonia\Hua.Todo.Avalonia.csproj"),
(Join-Path $ScriptPath "src\Hua.Todo.Desktop.Avalonia\Hua.Todo.Desktop.Avalonia.csproj")
)
$ProjectFile = Get-FirstExistingFilePath -Candidates $candidateProjects
if ($null -eq $ProjectFile) {
$candidatesText = ($candidateProjects | ForEach-Object { " - $_" }) -join "`n"
Write-Error @"
Avalonia Linux Linux
docs/project/-v1.2.0/01-Linux-AvaloniaWebView.md
$candidatesText
"@
exit 1
}
$version = Read-ProjectVersion -ProjectFile $ProjectFile -DirectoryBuildProps $DirectoryBuildProps
$ProjectBaseName = [System.IO.Path]::GetFileNameWithoutExtension($ProjectFile)
$artifactRoot = Join-Path $ScriptPath "artifacts\linux\$RuntimeIdentifier"
$publishDir = Join-Path $artifactRoot "publish"
if (Test-Path $artifactRoot) {
Remove-Item -Recurse -Force $artifactRoot
}
New-Item -ItemType Directory -Path $publishDir | Out-Null
$selfContainedValue = if ($SelfContained.IsPresent) { "true" } else { "false" }
if ($Configuration -ne "Release") {
Write-Host "⚠️ WARNING: You are publishing in $Configuration configuration!" -ForegroundColor Yellow
Write-Host " Typically, production artifacts MUST be in Release configuration." -ForegroundColor Yellow
Write-Host ""
}
if (!$SkipRestore.IsPresent) {
Write-Host "Restoring $ProjectBaseName for $RuntimeIdentifier ($TargetFramework)..." -ForegroundColor Yellow
$restoreArgs = @("restore", $ProjectFile, "-r", $RuntimeIdentifier, "-p:IsDesktopBuild=true", "-p:SkipWebBuild=true", "--verbosity", "minimal")
if (![string]::IsNullOrWhiteSpace($BaseIntermediateOutputPath)) {
# Ensure trailing slash and avoid backslash escaping the quote in CLI
$path = $BaseIntermediateOutputPath.TrimEnd('\') + '\'
$restoreArgs += "-p:BaseIntermediateOutputPath=$path"
}
& dotnet @restoreArgs
Write-Host "Cleaning $ProjectBaseName ($TargetFramework)..." -ForegroundColor Yellow
$cleanArgs = @("clean", $ProjectFile, "-c", $Configuration, "-r", $RuntimeIdentifier, "-p:IsDesktopBuild=true", "-p:SkipWebBuild=true", "--verbosity", "minimal")
if (![string]::IsNullOrWhiteSpace($BaseIntermediateOutputPath)) {
$path = $BaseIntermediateOutputPath.TrimEnd('\') + '\'
$cleanArgs += "-p:BaseIntermediateOutputPath=$path"
}
& dotnet @cleanArgs
}
$maxAttempts = 3
$publishSuccess = $false
for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
Write-Host "Publishing (RID=$RuntimeIdentifier, TFM=$TargetFramework, SelfContained=$selfContainedValue, Config=$Configuration, Attempt $attempt/$maxAttempts)..." -ForegroundColor Cyan
$publishArgs = @("publish", $ProjectFile, "-c", $Configuration, "-r", $RuntimeIdentifier, "--framework", $TargetFramework, "--self-contained", $selfContainedValue, "-p:IsDesktopBuild=true", "-p:SkipWebBuild=true", "-o", $publishDir)
if (![string]::IsNullOrWhiteSpace($BaseIntermediateOutputPath)) {
$path = $BaseIntermediateOutputPath.TrimEnd('\') + '\'
$publishArgs += "-p:BaseIntermediateOutputPath=$path"
}
$publishOutput = (& dotnet @publishArgs 2>&1 | Out-String)
$exitCode = $LASTEXITCODE
if ($exitCode -eq 0) {
$publishSuccess = $true
break
}
Write-Host $publishOutput
if ($attempt -lt $maxAttempts -and ($publishOutput -match 'Access to the path .* is denied|being used by another process|Sharing violation')) {
Write-Host "⚠️ Build failed due to file lock. Retrying in 3 seconds..." -ForegroundColor Yellow
Start-Sleep -Seconds 3
Stop-ProjectProcesses # Try killing processes again before retry
continue
}
Write-Error "dotnet publish failed after $attempt attempts."
exit 1
}
$packageName = "hua.todo-$version-$RuntimeIdentifier.tar.gz"
$packagePath = Join-Path $artifactRoot $packageName
Write-Host "Creating tar.gz: $packageName" -ForegroundColor Cyan
tar -C $publishDir -czf $packagePath .
if ($LASTEXITCODE -ne 0) {
Write-Error "tar.gz packaging failed"
exit 1
}
Write-Host "Linux artifact created: $packagePath" -ForegroundColor Green