mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-23 18:04:26 +08:00
Compare commits
3 Commits
8323b8cb61
...
d31aa90b9c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d31aa90b9c | ||
|
|
0878bcab5a | ||
|
|
4d5bea0c46 |
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@@ -732,6 +732,8 @@ jobs:
|
|||||||
AWS_DEFAULT_REGION: ${{ vars.S3_REGION }}
|
AWS_DEFAULT_REGION: ${{ vars.S3_REGION }}
|
||||||
AWS_REGION: ${{ vars.S3_REGION }}
|
AWS_REGION: ${{ vars.S3_REGION }}
|
||||||
AWS_EC2_METADATA_DISABLED: "true"
|
AWS_EC2_METADATA_DISABLED: "true"
|
||||||
|
AWS_REQUEST_CHECKSUM_CALCULATION: "WHEN_REQUIRED"
|
||||||
|
AWS_RESPONSE_CHECKSUM_VALIDATION: "WHEN_REQUIRED"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -806,6 +808,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
aws --version
|
||||||
aws --endpoint-url "$S3_ENDPOINT" --region "$S3_REGION" s3 ls "s3://$S3_BUCKET" >/dev/null
|
aws --endpoint-url "$S3_ENDPOINT" --region "$S3_REGION" s3 ls "s3://$S3_BUCKET" >/dev/null
|
||||||
echo "S3 access probe succeeded for $S3_BUCKET"
|
echo "S3 access probe succeeded for $S3_BUCKET"
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ function Resolve-AppDirectory {
|
|||||||
return $fallback?.FullName
|
return $fallback?.FullName
|
||||||
}
|
}
|
||||||
|
|
||||||
function Invoke-AwsSyncIfPossible {
|
function Invoke-AwsCommandIfPossible {
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string[]]$Arguments,
|
[string[]]$Arguments,
|
||||||
@@ -80,18 +80,208 @@ function Invoke-AwsSyncIfPossible {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$previousRequestChecksumCalculation = $env:AWS_REQUEST_CHECKSUM_CALCULATION
|
||||||
|
$previousResponseChecksumValidation = $env:AWS_RESPONSE_CHECKSUM_VALIDATION
|
||||||
|
|
||||||
|
# Rainyun's S3-compatible endpoint rejects AWS CLI v2's default checksum headers
|
||||||
|
# during multipart uploads. Restrict checksum behavior to API-required cases only.
|
||||||
|
$env:AWS_REQUEST_CHECKSUM_CALCULATION = "WHEN_REQUIRED"
|
||||||
|
$env:AWS_RESPONSE_CHECKSUM_VALIDATION = "WHEN_REQUIRED"
|
||||||
|
|
||||||
|
try {
|
||||||
if ($IgnoreFailure) {
|
if ($IgnoreFailure) {
|
||||||
& aws @Arguments 2>$null
|
& aws @Arguments 2>$null
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
& aws @Arguments
|
& aws @Arguments
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ($null -eq $previousRequestChecksumCalculation) {
|
||||||
|
Remove-Item Env:AWS_REQUEST_CHECKSUM_CALCULATION -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$env:AWS_REQUEST_CHECKSUM_CALCULATION = $previousRequestChecksumCalculation
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -eq $previousResponseChecksumValidation) {
|
||||||
|
Remove-Item Env:AWS_RESPONSE_CHECKSUM_VALIDATION -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$env:AWS_RESPONSE_CHECKSUM_VALIDATION = $previousResponseChecksumValidation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($LASTEXITCODE -ne 0 -and -not $IgnoreFailure) {
|
if ($LASTEXITCODE -ne 0 -and -not $IgnoreFailure) {
|
||||||
throw "aws command failed: aws $($Arguments -join ' ')"
|
throw "aws command failed: aws $($Arguments -join ' ')"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Get-S3Key {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Prefix,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$RelativePath
|
||||||
|
)
|
||||||
|
|
||||||
|
$trimmedPrefix = $Prefix.Trim('/').Replace('\', '/')
|
||||||
|
$trimmedRelativePath = $RelativePath.TrimStart('\', '/').Replace('\', '/')
|
||||||
|
return "$trimmedPrefix/$trimmedRelativePath"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-RelativePath {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Root,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Path
|
||||||
|
)
|
||||||
|
|
||||||
|
$rootPath = [System.IO.Path]::GetFullPath($Root)
|
||||||
|
if (-not $rootPath.EndsWith([System.IO.Path]::DirectorySeparatorChar)) {
|
||||||
|
$rootPath += [System.IO.Path]::DirectorySeparatorChar
|
||||||
|
}
|
||||||
|
|
||||||
|
$pathValue = [System.IO.Path]::GetFullPath($Path)
|
||||||
|
return [System.IO.Path]::GetRelativePath($rootPath, $pathValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-RemoteS3Keys {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Prefix
|
||||||
|
)
|
||||||
|
|
||||||
|
$keys = [System.Collections.Generic.List[string]]::new()
|
||||||
|
$continuationToken = $null
|
||||||
|
|
||||||
|
do {
|
||||||
|
$arguments = @(
|
||||||
|
"--endpoint-url", $S3Endpoint,
|
||||||
|
"--region", $S3Region,
|
||||||
|
"s3api", "list-objects-v2",
|
||||||
|
"--bucket", $S3Bucket,
|
||||||
|
"--prefix", $Prefix,
|
||||||
|
"--output", "json"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($continuationToken)) {
|
||||||
|
$arguments += @("--continuation-token", $continuationToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
$json = Invoke-AwsCommandIfPossible -Arguments $arguments
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($json)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $json | ConvertFrom-Json
|
||||||
|
if ($response.Contents) {
|
||||||
|
foreach ($item in $response.Contents) {
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($item.Key)) {
|
||||||
|
$keys.Add($item.Key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($response.IsTruncated -and -not [string]::IsNullOrWhiteSpace($response.NextContinuationToken)) {
|
||||||
|
$continuationToken = $response.NextContinuationToken
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$continuationToken = $null
|
||||||
|
}
|
||||||
|
} while (-not [string]::IsNullOrWhiteSpace($continuationToken))
|
||||||
|
|
||||||
|
return $keys
|
||||||
|
}
|
||||||
|
|
||||||
|
function Upload-DirectoryToS3 {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$LocalRoot,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$RemotePrefix,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[switch]$DeleteExtraRemoteObjects
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $LocalRoot)) {
|
||||||
|
throw "Local upload root not found: $LocalRoot"
|
||||||
|
}
|
||||||
|
|
||||||
|
$files = Get-ChildItem -LiteralPath $LocalRoot -Recurse -File | Sort-Object FullName
|
||||||
|
$uploadedKeys = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal)
|
||||||
|
|
||||||
|
if ($files.Count -eq 0) {
|
||||||
|
Write-Host "No files found under $LocalRoot; skipping upload."
|
||||||
|
}
|
||||||
|
|
||||||
|
$index = 0
|
||||||
|
foreach ($file in $files) {
|
||||||
|
$index++
|
||||||
|
$relativePath = Get-RelativePath -Root $LocalRoot -Path $file.FullName
|
||||||
|
$key = Get-S3Key -Prefix $RemotePrefix -RelativePath $relativePath
|
||||||
|
$null = $uploadedKeys.Add($key)
|
||||||
|
|
||||||
|
if ($index -eq 1 -or $index % 25 -eq 0 -or $index -eq $files.Count) {
|
||||||
|
Write-Host "Uploading $index/$($files.Count): $key"
|
||||||
|
}
|
||||||
|
|
||||||
|
Invoke-AwsCommandIfPossible -Arguments @(
|
||||||
|
"--endpoint-url", $S3Endpoint,
|
||||||
|
"--region", $S3Region,
|
||||||
|
"s3api", "put-object",
|
||||||
|
"--bucket", $S3Bucket,
|
||||||
|
"--key", $key,
|
||||||
|
"--body", $file.FullName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($DeleteExtraRemoteObjects) {
|
||||||
|
$remoteKeys = Get-RemoteS3Keys -Prefix $RemotePrefix.Trim('/').Replace('\', '/')
|
||||||
|
foreach ($remoteKey in $remoteKeys) {
|
||||||
|
if (-not $uploadedKeys.Contains($remoteKey)) {
|
||||||
|
Write-Host "Deleting stale remote object: $remoteKey"
|
||||||
|
Invoke-AwsCommandIfPossible -Arguments @(
|
||||||
|
"--endpoint-url", $S3Endpoint,
|
||||||
|
"--region", $S3Region,
|
||||||
|
"s3api", "delete-object",
|
||||||
|
"--bucket", $S3Bucket,
|
||||||
|
"--key", $remoteKey
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Upload-FileToS3 {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$LocalPath,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$RemoteKey
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $LocalPath)) {
|
||||||
|
throw "Local upload file not found: $LocalPath"
|
||||||
|
}
|
||||||
|
|
||||||
|
Invoke-AwsCommandIfPossible -Arguments @(
|
||||||
|
"--endpoint-url", $S3Endpoint,
|
||||||
|
"--region", $S3Region,
|
||||||
|
"s3api", "put-object",
|
||||||
|
"--bucket", $S3Bucket,
|
||||||
|
"--key", $RemoteKey.Trim('/').Replace('\', '/'),
|
||||||
|
"--body", $LocalPath
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (-not (Test-Path -LiteralPath $PrivateKeyPath)) {
|
if (-not (Test-Path -LiteralPath $PrivateKeyPath)) {
|
||||||
throw "Private key file not found: $PrivateKeyPath"
|
throw "Private key file not found: $PrivateKeyPath"
|
||||||
}
|
}
|
||||||
@@ -119,7 +309,7 @@ foreach ($config in $supportedPlatforms) {
|
|||||||
New-Item -ItemType Directory -Path $baselineCurrentDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $baselineCurrentDir -Force | Out-Null
|
||||||
|
|
||||||
if (-not [string]::IsNullOrWhiteSpace($S3Endpoint) -and -not [string]::IsNullOrWhiteSpace($S3Bucket)) {
|
if (-not [string]::IsNullOrWhiteSpace($S3Endpoint) -and -not [string]::IsNullOrWhiteSpace($S3Bucket)) {
|
||||||
Invoke-AwsSyncIfPossible -Arguments @(
|
Invoke-AwsCommandIfPossible -Arguments @(
|
||||||
"--endpoint-url", $S3Endpoint,
|
"--endpoint-url", $S3Endpoint,
|
||||||
"--region", $S3Region,
|
"--region", $S3Region,
|
||||||
"s3", "sync",
|
"s3", "sync",
|
||||||
@@ -128,7 +318,7 @@ foreach ($config in $supportedPlatforms) {
|
|||||||
"--only-show-errors"
|
"--only-show-errors"
|
||||||
) -IgnoreFailure
|
) -IgnoreFailure
|
||||||
|
|
||||||
Invoke-AwsSyncIfPossible -Arguments @(
|
Invoke-AwsCommandIfPossible -Arguments @(
|
||||||
"--endpoint-url", $S3Endpoint,
|
"--endpoint-url", $S3Endpoint,
|
||||||
"--region", $S3Region,
|
"--region", $S3Region,
|
||||||
"s3", "cp",
|
"s3", "cp",
|
||||||
@@ -173,9 +363,11 @@ foreach ($config in $supportedPlatforms) {
|
|||||||
"0.0.0"
|
"0.0.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
$baselineHasContent = Get-ChildItem -LiteralPath $baselineCurrentDir -Force -ErrorAction SilentlyContinue | Select-Object -First 1
|
$baselineItems = @(Get-ChildItem -LiteralPath $baselineCurrentDir -Force -ErrorAction SilentlyContinue)
|
||||||
if ($baselineHasContent) {
|
if ($baselineItems.Count -gt 0) {
|
||||||
Copy-Item -LiteralPath (Join-Path $baselineCurrentDir '*') -Destination $snapshotRoot -Recurse -Force
|
foreach ($baselineItem in $baselineItems) {
|
||||||
|
Copy-Item -LiteralPath $baselineItem.FullName -Destination $snapshotRoot -Recurse -Force
|
||||||
|
}
|
||||||
$snapshotDir = $snapshotRoot
|
$snapshotDir = $snapshotRoot
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -266,14 +458,7 @@ foreach ($config in $supportedPlatforms) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (-not [string]::IsNullOrWhiteSpace($S3Endpoint) -and -not [string]::IsNullOrWhiteSpace($S3Bucket)) {
|
if (-not [string]::IsNullOrWhiteSpace($S3Endpoint) -and -not [string]::IsNullOrWhiteSpace($S3Bucket)) {
|
||||||
Invoke-AwsSyncIfPossible -Arguments @(
|
Upload-DirectoryToS3 -LocalRoot $publishedRoot -RemotePrefix "lanmountain/update"
|
||||||
"--endpoint-url", $S3Endpoint,
|
|
||||||
"--region", $S3Region,
|
|
||||||
"s3", "sync",
|
|
||||||
$publishedRoot,
|
|
||||||
"s3://$S3Bucket/lanmountain/update/",
|
|
||||||
"--only-show-errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
foreach ($config in $supportedPlatforms) {
|
foreach ($config in $supportedPlatforms) {
|
||||||
$platform = $config.Platform
|
$platform = $config.Platform
|
||||||
@@ -281,24 +466,14 @@ if (-not [string]::IsNullOrWhiteSpace($S3Endpoint) -and -not [string]::IsNullOrW
|
|||||||
$baselineCurrentDir = Join-Path $platformBaselineRoot "current"
|
$baselineCurrentDir = Join-Path $platformBaselineRoot "current"
|
||||||
$baselineVersionPath = Join-Path $platformBaselineRoot "version.txt"
|
$baselineVersionPath = Join-Path $platformBaselineRoot "version.txt"
|
||||||
|
|
||||||
Invoke-AwsSyncIfPossible -Arguments @(
|
Upload-DirectoryToS3 `
|
||||||
"--endpoint-url", $S3Endpoint,
|
-LocalRoot $baselineCurrentDir `
|
||||||
"--region", $S3Region,
|
-RemotePrefix "lanmountain/update/baselines/$platform/current" `
|
||||||
"s3", "sync",
|
-DeleteExtraRemoteObjects
|
||||||
$baselineCurrentDir,
|
|
||||||
"s3://$S3Bucket/lanmountain/update/baselines/$platform/current/",
|
|
||||||
"--delete",
|
|
||||||
"--only-show-errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
Invoke-AwsSyncIfPossible -Arguments @(
|
Upload-FileToS3 `
|
||||||
"--endpoint-url", $S3Endpoint,
|
-LocalPath $baselineVersionPath `
|
||||||
"--region", $S3Region,
|
-RemoteKey "lanmountain/update/baselines/$platform/version.txt"
|
||||||
"s3", "cp",
|
|
||||||
$baselineVersionPath,
|
|
||||||
"s3://$S3Bucket/lanmountain/update/baselines/$platform/version.txt",
|
|
||||||
"--only-show-errors"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user