mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-23 01:44:26 +08:00
feat.Publisher完整包上传
This commit is contained in:
6
.github/workflows/plonds-uploader.yml
vendored
6
.github/workflows/plonds-uploader.yml
vendored
@@ -75,9 +75,10 @@ jobs:
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
rm -rf plonds-assets
|
rm -rf plonds-assets
|
||||||
mkdir -p plonds-assets
|
mkdir -p plonds-assets
|
||||||
gh release download "$RELEASE_TAG" -p changed.zip -p PLONDS.json -D plonds-assets --clobber
|
gh release download "$RELEASE_TAG" -p changed.zip -p PLONDS.json -p files-windows-x64.zip -D plonds-assets --clobber
|
||||||
test -f plonds-assets/changed.zip
|
test -f plonds-assets/changed.zip
|
||||||
test -f plonds-assets/PLONDS.json
|
test -f plonds-assets/PLONDS.json
|
||||||
|
test -f plonds-assets/files-windows-x64.zip
|
||||||
jq -e . plonds-assets/PLONDS.json >/dev/null
|
jq -e . plonds-assets/PLONDS.json >/dev/null
|
||||||
|
|
||||||
- name: Publish PLONDS assets to Rainyun S3
|
- name: Publish PLONDS assets to Rainyun S3
|
||||||
@@ -106,6 +107,7 @@ jobs:
|
|||||||
--repository "${{ github.repository }}" \
|
--repository "${{ github.repository }}" \
|
||||||
--manifest "$PWD/plonds-assets/PLONDS.json" \
|
--manifest "$PWD/plonds-assets/PLONDS.json" \
|
||||||
--changed-zip "$PWD/plonds-assets/changed.zip" \
|
--changed-zip "$PWD/plonds-assets/changed.zip" \
|
||||||
|
--files-zip "$PWD/plonds-assets/files-windows-x64.zip" \
|
||||||
--work-dir "$PWD/plonds-publish-work" \
|
--work-dir "$PWD/plonds-publish-work" \
|
||||||
--s3-prefix "$PLONDS_S3_PREFIX" \
|
--s3-prefix "$PLONDS_S3_PREFIX" \
|
||||||
--s3-endpoint "$S3_ENDPOINT" \
|
--s3-endpoint "$S3_ENDPOINT" \
|
||||||
@@ -116,7 +118,7 @@ jobs:
|
|||||||
--s3-public-base-url "$PUBLIC_BASE" \
|
--s3-public-base-url "$PUBLIC_BASE" \
|
||||||
--s3-public-base-key-prefix "$PLONDS_S3_PUBLIC_BASE_KEY_PREFIX"
|
--s3-public-base-key-prefix "$PLONDS_S3_PUBLIC_BASE_KEY_PREFIX"
|
||||||
|
|
||||||
jq -e '.downloads.github.changedZipUrl and .downloads.s3.changedFolderUrl' plonds-assets/PLONDS.json >/dev/null
|
jq -e '.downloads.github.changedZipUrl and .downloads.github.filesZipUrl and .downloads.s3.changedFolderUrl and .downloads.s3.filesFolderUrl' plonds-assets/PLONDS.json >/dev/null
|
||||||
|
|
||||||
- name: Upload enriched PLONDS manifest to GitHub Release
|
- name: Upload enriched PLONDS manifest to GitHub Release
|
||||||
env:
|
env:
|
||||||
|
|||||||
170
.trae/specs/plonds-client-service/spec.md
Normal file
170
.trae/specs/plonds-client-service/spec.md
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
# PLONDS Client Service 独立化设计
|
||||||
|
|
||||||
|
> 日期:2026-06-01
|
||||||
|
> 状态:设计中
|
||||||
|
|
||||||
|
## 1. 目标
|
||||||
|
|
||||||
|
PLONDS 在应用内必须作为独立服务存在,负责分发发现、下载、校验和本地包准备。它不是现有 Update 模块的 provider,也不应把 S3/GitHub/source 选择逻辑混入 `LanMountainDesktop/Services/Update/`。
|
||||||
|
|
||||||
|
最终边界:
|
||||||
|
|
||||||
|
- PLONDS 服务:寻找最新版本、选择下载源、下载 manifest 和包、校验文件、准备本地 staging。
|
||||||
|
- 安装程序/安装网关:只消费 PLONDS 已准备好的本地安装输入,执行增量安装或完整安装。
|
||||||
|
- UI:只展示 PLONDS 服务和安装程序返回的状态;完整包也失败后才处理错误。
|
||||||
|
|
||||||
|
## 2. 当前耦合点
|
||||||
|
|
||||||
|
当前需要拆离的耦合点:
|
||||||
|
|
||||||
|
- `LanMountainDesktop/Services/Settings/SettingsDomainServices.cs`
|
||||||
|
- 直接持有 `PlondsStaticUpdateService` 与 `PlondsReleaseUpdateService`
|
||||||
|
- 在 `CheckForUpdatesCoreAsync` 中把 PLONDS 和 GitHub Update fallback 逻辑混在一起
|
||||||
|
- `LanMountainDesktop/Services/Update/UpdateInstallGateway.cs`
|
||||||
|
- 直接判断 `UpdatePayloadKind.DeltaPlonds`
|
||||||
|
- 直接实例化 `PlondsUpdateApplier`
|
||||||
|
- `LanMountainDesktop/Services/Update/Plonds*.cs`
|
||||||
|
- PLONDS apply/parser/payload resolver 仍位于 Update 命名空间
|
||||||
|
|
||||||
|
## 3. Source 发现规则
|
||||||
|
|
||||||
|
PLONDS 客户端内置两个初始地址:
|
||||||
|
|
||||||
|
1. S3 上的 PLONDS manifest 地址
|
||||||
|
2. GitHub Release 上的 PLONDS manifest 地址
|
||||||
|
|
||||||
|
两个地址读取的是同一种 JSON 文件,当前文件名为 `PLONDS.json`。客户端每次检查增量更新时,会并行或顺序请求所有已知 source 的 `PLONDS.json`。
|
||||||
|
|
||||||
|
### 3.1 Source 扩展
|
||||||
|
|
||||||
|
`PLONDS.json` 可以声明额外 source。客户端读取到额外 source 后,应把它们加入下一轮寻找列表。
|
||||||
|
|
||||||
|
建议 manifest 扩展字段:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"id": "rainyun-s3",
|
||||||
|
"kind": "s3",
|
||||||
|
"manifestUrl": "https://example.com/plonds/1.2.3/PLONDS.json",
|
||||||
|
"priority": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "github",
|
||||||
|
"kind": "github",
|
||||||
|
"manifestUrl": "https://github.com/owner/repo/releases/download/v1.2.3/PLONDS.json",
|
||||||
|
"priority": 50
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
规则:
|
||||||
|
|
||||||
|
- `sources` 为空或缺失时,只使用内置 S3 + GitHub。
|
||||||
|
- 新 source 不覆盖内置 source,除非 `id` 相同。
|
||||||
|
- source 列表需要去重,按 `id` 和 `manifestUrl` 双重去重。
|
||||||
|
- source 持久化到 PLONDS 自己的配置/缓存,不写入 Update 设置。
|
||||||
|
|
||||||
|
## 4. 版本选择规则
|
||||||
|
|
||||||
|
如果多个 source 返回的版本不一致,客户端选择 `currentVersion` 最高的 manifest。
|
||||||
|
|
||||||
|
规则:
|
||||||
|
|
||||||
|
- 版本解析使用 `Version` 语义,忽略前导 `v`。
|
||||||
|
- 版本相同时,优先选择下载可用性更高的 source。
|
||||||
|
- 如果最高版本 manifest 下载包失败,可以尝试同版本的其他 source。
|
||||||
|
- 不因为低版本 source 成功而降级,除非用户显式允许。
|
||||||
|
|
||||||
|
## 5. 下载与回退规则
|
||||||
|
|
||||||
|
PLONDS 服务优先走增量包:
|
||||||
|
|
||||||
|
1. 下载所选 manifest。
|
||||||
|
2. 下载 `changed.zip`。
|
||||||
|
3. 校验 `changed.zip` 与 manifest 中的 hash/checksum。
|
||||||
|
4. 解压或准备增量 staging。
|
||||||
|
5. 交给安装程序执行增量安装。
|
||||||
|
|
||||||
|
如果增量流程失败,PLONDS 服务自动改用完整包:
|
||||||
|
|
||||||
|
1. 下载 `Files.zip`。
|
||||||
|
2. 校验 `Files.zip`。
|
||||||
|
3. 解压或准备完整包 staging。
|
||||||
|
4. 交给安装程序执行完整包安装。
|
||||||
|
|
||||||
|
如果完整包也失败,PLONDS 服务返回失败结果,由 UI 展示错误和重试入口。
|
||||||
|
|
||||||
|
## 6. 发布产物布局
|
||||||
|
|
||||||
|
Publisher 上传到 S3 的版本目录:
|
||||||
|
|
||||||
|
```text
|
||||||
|
<prefix>/<version>/PLONDS.json
|
||||||
|
<prefix>/<version>/changed.zip
|
||||||
|
<prefix>/<version>/<version>-changed/**
|
||||||
|
<prefix>/<version>/Files.zip
|
||||||
|
<prefix>/<version>/<version>-Files/**
|
||||||
|
```
|
||||||
|
|
||||||
|
说明:
|
||||||
|
|
||||||
|
- `Files.zip` 是上传到 S3 时的完整包标准名。
|
||||||
|
- `<version>-Files/` 是 S3 上解压后的完整包目录。
|
||||||
|
- GitHub Release 仍可保留平台原始文件名,例如 `files-windows-x64.zip`。
|
||||||
|
- `PLONDS.json` 的 downloads 字段同时包含 GitHub 与 S3 的增量包、完整包位置。
|
||||||
|
|
||||||
|
## 7. 建议代码结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
LanMountainDesktop/Services/Plonds/
|
||||||
|
IPlondsService.cs
|
||||||
|
PlondsService.cs
|
||||||
|
Sources/
|
||||||
|
IPlondsSource.cs
|
||||||
|
PlondsHttpManifestSource.cs
|
||||||
|
PlondsSourceRegistry.cs
|
||||||
|
Download/
|
||||||
|
PlondsDownloader.cs
|
||||||
|
PlondsDownloadPlanner.cs
|
||||||
|
Verification/
|
||||||
|
PlondsVerifier.cs
|
||||||
|
Staging/
|
||||||
|
PlondsPackageStore.cs
|
||||||
|
PlondsPreparedPackage.cs
|
||||||
|
Models/
|
||||||
|
PlondsClientManifest.cs
|
||||||
|
PlondsSourceDescriptor.cs
|
||||||
|
PlondsCheckResult.cs
|
||||||
|
```
|
||||||
|
|
||||||
|
后续如果要移植,优先把这棵目录或等价项目抽成独立库。
|
||||||
|
|
||||||
|
## 8. 与安装程序的交接契约
|
||||||
|
|
||||||
|
PLONDS 服务输出本地 prepared package:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public sealed record PlondsPreparedPackage(
|
||||||
|
Version Version,
|
||||||
|
PlondsPackageMode Mode,
|
||||||
|
string ManifestPath,
|
||||||
|
string? ChangedZipPath,
|
||||||
|
string? ChangedDirectory,
|
||||||
|
string? FilesZipPath,
|
||||||
|
string? FilesDirectory);
|
||||||
|
```
|
||||||
|
|
||||||
|
安装程序只接受这个结果,不参与 source 发现、下载和校验。
|
||||||
|
|
||||||
|
## 9. 实施顺序
|
||||||
|
|
||||||
|
1. Publisher 补齐完整包 S3 上传与 manifest downloads 字段。
|
||||||
|
2. 新增 `Services/Plonds/` 客户端服务骨架和模型。
|
||||||
|
3. 把 `PlondsStaticUpdateService` / `PlondsReleaseUpdateService` 合并迁移到独立 PLONDS source 体系。
|
||||||
|
4. 把 `LanMountainDesktop/Services/Update/Plonds*.cs` 迁出 Update 命名空间。
|
||||||
|
5. `UpdateSettingsService` 改为调用 `IPlondsService`,不再直接组合 S3/GitHub PLONDS fallback。
|
||||||
|
6. 安装入口只接收 `PlondsPreparedPackage`。
|
||||||
|
7. 添加单元测试覆盖 source 扩展、最高版本选择、增量失败转完整包、完整包失败交 UI。
|
||||||
@@ -319,13 +319,18 @@ jobs:
|
|||||||
<prefix>/<version>/PLONDS.json
|
<prefix>/<version>/PLONDS.json
|
||||||
<prefix>/<version>/changed.zip
|
<prefix>/<version>/changed.zip
|
||||||
<prefix>/<version>/<version>-changed/**
|
<prefix>/<version>/<version>-changed/**
|
||||||
|
<prefix>/<version>/Files.zip
|
||||||
|
<prefix>/<version>/<version>-Files/**
|
||||||
→ 回写 PLONDS.json downloads 字段:
|
→ 回写 PLONDS.json downloads 字段:
|
||||||
downloads.github.releaseUrl
|
downloads.github.releaseUrl
|
||||||
downloads.github.manifestUrl
|
downloads.github.manifestUrl
|
||||||
downloads.github.changedZipUrl
|
downloads.github.changedZipUrl
|
||||||
|
downloads.github.filesZipUrl
|
||||||
downloads.s3.manifestUrl
|
downloads.s3.manifestUrl
|
||||||
downloads.s3.changedZipUrl
|
downloads.s3.changedZipUrl
|
||||||
downloads.s3.changedFolderUrl
|
downloads.s3.changedFolderUrl
|
||||||
|
downloads.s3.filesZipUrl
|
||||||
|
downloads.s3.filesFolderUrl
|
||||||
- 将回写后的 PLONDS.json 重新上传到 GitHub Release
|
- 将回写后的 PLONDS.json 重新上传到 GitHub Release
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ public sealed record PlondsPublishOptions(
|
|||||||
string Repository,
|
string Repository,
|
||||||
string ManifestPath,
|
string ManifestPath,
|
||||||
string ChangedZipPath,
|
string ChangedZipPath,
|
||||||
|
string FilesZipPath,
|
||||||
string WorkDir,
|
string WorkDir,
|
||||||
string S3KeyPrefix,
|
string S3KeyPrefix,
|
||||||
PlondsS3ClientOptions S3);
|
PlondsS3ClientOptions S3);
|
||||||
|
|||||||
@@ -10,4 +10,9 @@ public sealed record PlondsPublishResult(
|
|||||||
string ChangedZipUrl,
|
string ChangedZipUrl,
|
||||||
string ChangedFolderKey,
|
string ChangedFolderKey,
|
||||||
string ChangedFolderUrl,
|
string ChangedFolderUrl,
|
||||||
int ChangedFileCount);
|
string FilesZipKey,
|
||||||
|
string FilesZipUrl,
|
||||||
|
string FilesFolderKey,
|
||||||
|
string FilesFolderUrl,
|
||||||
|
int ChangedFileCount,
|
||||||
|
int FilesFileCount);
|
||||||
|
|||||||
@@ -21,12 +21,15 @@ public sealed class PlondsPublisher
|
|||||||
var repository = Require(options.Repository, nameof(options.Repository));
|
var repository = Require(options.Repository, nameof(options.Repository));
|
||||||
var manifestPath = Path.GetFullPath(Require(options.ManifestPath, nameof(options.ManifestPath)));
|
var manifestPath = Path.GetFullPath(Require(options.ManifestPath, nameof(options.ManifestPath)));
|
||||||
var changedZipPath = Path.GetFullPath(Require(options.ChangedZipPath, nameof(options.ChangedZipPath)));
|
var changedZipPath = Path.GetFullPath(Require(options.ChangedZipPath, nameof(options.ChangedZipPath)));
|
||||||
|
var filesZipPath = Path.GetFullPath(Require(options.FilesZipPath, nameof(options.FilesZipPath)));
|
||||||
var workDir = Path.GetFullPath(Require(options.WorkDir, nameof(options.WorkDir)));
|
var workDir = Path.GetFullPath(Require(options.WorkDir, nameof(options.WorkDir)));
|
||||||
var version = releaseTag.TrimStart('v', 'V');
|
var version = releaseTag.TrimStart('v', 'V');
|
||||||
var prefix = NormalizePrefix(options.S3KeyPrefix);
|
var prefix = NormalizePrefix(options.S3KeyPrefix);
|
||||||
var versionPrefix = $"{prefix}/{version}";
|
var versionPrefix = $"{prefix}/{version}";
|
||||||
var changedFolderName = $"{version}-changed";
|
var changedFolderName = $"{version}-changed";
|
||||||
|
var filesFolderName = $"{version}-Files";
|
||||||
var changedExtractRoot = Path.Combine(workDir, changedFolderName);
|
var changedExtractRoot = Path.Combine(workDir, changedFolderName);
|
||||||
|
var filesExtractRoot = Path.Combine(workDir, filesFolderName);
|
||||||
|
|
||||||
if (!File.Exists(manifestPath))
|
if (!File.Exists(manifestPath))
|
||||||
{
|
{
|
||||||
@@ -38,26 +41,30 @@ public sealed class PlondsPublisher
|
|||||||
throw new FileNotFoundException("PLONDS changed.zip not found.", changedZipPath);
|
throw new FileNotFoundException("PLONDS changed.zip not found.", changedZipPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(filesZipPath))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("PLONDS files zip not found.", filesZipPath);
|
||||||
|
}
|
||||||
|
|
||||||
var manifest = LoadManifest(manifestPath);
|
var manifest = LoadManifest(manifestPath);
|
||||||
PayloadUtilities.EnsureCleanDirectory(changedExtractRoot);
|
PayloadUtilities.EnsureCleanDirectory(changedExtractRoot);
|
||||||
ZipFile.ExtractToDirectory(changedZipPath, changedExtractRoot, overwriteFiles: true);
|
ZipFile.ExtractToDirectory(changedZipPath, changedExtractRoot, overwriteFiles: true);
|
||||||
|
PayloadUtilities.EnsureCleanDirectory(filesExtractRoot);
|
||||||
|
ZipFile.ExtractToDirectory(filesZipPath, filesExtractRoot, overwriteFiles: true);
|
||||||
|
|
||||||
var manifestKey = $"{versionPrefix}/PLONDS.json";
|
var manifestKey = $"{versionPrefix}/PLONDS.json";
|
||||||
var changedZipKey = $"{versionPrefix}/changed.zip";
|
var changedZipKey = $"{versionPrefix}/changed.zip";
|
||||||
var changedFolderKey = $"{versionPrefix}/{changedFolderName}";
|
var changedFolderKey = $"{versionPrefix}/{changedFolderName}";
|
||||||
|
var filesZipKey = $"{versionPrefix}/Files.zip";
|
||||||
|
var filesFolderKey = $"{versionPrefix}/{filesFolderName}";
|
||||||
|
|
||||||
using var s3 = new PlondsS3Client(options.S3);
|
using var s3 = new PlondsS3Client(options.S3);
|
||||||
|
|
||||||
var changedFileCount = 0;
|
var changedFileCount = await UploadDirectoryAsync(s3, changedExtractRoot, changedFolderKey, cancellationToken).ConfigureAwait(false);
|
||||||
foreach (var filePath in Directory.EnumerateFiles(changedExtractRoot, "*", SearchOption.AllDirectories).OrderBy(x => x, StringComparer.OrdinalIgnoreCase))
|
var filesFileCount = await UploadDirectoryAsync(s3, filesExtractRoot, filesFolderKey, cancellationToken).ConfigureAwait(false);
|
||||||
{
|
|
||||||
var relativePath = PayloadUtilities.NormalizeRelativePath(Path.GetRelativePath(changedExtractRoot, filePath));
|
|
||||||
var objectKey = $"{changedFolderKey}/{relativePath}";
|
|
||||||
await s3.UploadFileAsync(new PlondsS3ObjectUpload(filePath, objectKey, ResolveContentType(filePath)), cancellationToken).ConfigureAwait(false);
|
|
||||||
changedFileCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
await s3.UploadFileAsync(new PlondsS3ObjectUpload(changedZipPath, changedZipKey, "application/zip"), cancellationToken).ConfigureAwait(false);
|
await s3.UploadFileAsync(new PlondsS3ObjectUpload(changedZipPath, changedZipKey, "application/zip"), cancellationToken).ConfigureAwait(false);
|
||||||
|
await s3.UploadFileAsync(new PlondsS3ObjectUpload(filesZipPath, filesZipKey, "application/zip"), cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var updatedManifest = manifest with
|
var updatedManifest = manifest with
|
||||||
{
|
{
|
||||||
@@ -66,7 +73,8 @@ public sealed class PlondsPublisher
|
|||||||
GitHub: new PlondsGitHubDownloadInfo(
|
GitHub: new PlondsGitHubDownloadInfo(
|
||||||
ReleaseUrl: $"https://github.com/{repository}/releases/tag/{releaseTag}",
|
ReleaseUrl: $"https://github.com/{repository}/releases/tag/{releaseTag}",
|
||||||
ManifestUrl: $"https://github.com/{repository}/releases/download/{releaseTag}/PLONDS.json",
|
ManifestUrl: $"https://github.com/{repository}/releases/download/{releaseTag}/PLONDS.json",
|
||||||
ChangedZipUrl: $"https://github.com/{repository}/releases/download/{releaseTag}/changed.zip"),
|
ChangedZipUrl: $"https://github.com/{repository}/releases/download/{releaseTag}/changed.zip",
|
||||||
|
FilesZipUrl: $"https://github.com/{repository}/releases/download/{releaseTag}/{Path.GetFileName(filesZipPath)}"),
|
||||||
S3: new PlondsS3DownloadInfo(
|
S3: new PlondsS3DownloadInfo(
|
||||||
Bucket: options.S3.Bucket,
|
Bucket: options.S3.Bucket,
|
||||||
Prefix: versionPrefix,
|
Prefix: versionPrefix,
|
||||||
@@ -75,7 +83,11 @@ public sealed class PlondsPublisher
|
|||||||
ChangedZipKey: changedZipKey,
|
ChangedZipKey: changedZipKey,
|
||||||
ChangedZipUrl: s3.BuildPublicUrl(changedZipKey),
|
ChangedZipUrl: s3.BuildPublicUrl(changedZipKey),
|
||||||
ChangedFolderKey: changedFolderKey,
|
ChangedFolderKey: changedFolderKey,
|
||||||
ChangedFolderUrl: s3.BuildPublicUrl(changedFolderKey)))
|
ChangedFolderUrl: s3.BuildPublicUrl(changedFolderKey),
|
||||||
|
FilesZipKey: filesZipKey,
|
||||||
|
FilesZipUrl: s3.BuildPublicUrl(filesZipKey),
|
||||||
|
FilesFolderKey: filesFolderKey,
|
||||||
|
FilesFolderUrl: s3.BuildPublicUrl(filesFolderKey)))
|
||||||
};
|
};
|
||||||
|
|
||||||
File.WriteAllText(manifestPath, JsonSerializer.Serialize(updatedManifest, JsonOptions), new UTF8Encoding(false));
|
File.WriteAllText(manifestPath, JsonSerializer.Serialize(updatedManifest, JsonOptions), new UTF8Encoding(false));
|
||||||
@@ -83,6 +95,7 @@ public sealed class PlondsPublisher
|
|||||||
|
|
||||||
await s3.EnsureObjectExistsAsync(manifestKey, cancellationToken).ConfigureAwait(false);
|
await s3.EnsureObjectExistsAsync(manifestKey, cancellationToken).ConfigureAwait(false);
|
||||||
await s3.EnsureObjectExistsAsync(changedZipKey, cancellationToken).ConfigureAwait(false);
|
await s3.EnsureObjectExistsAsync(changedZipKey, cancellationToken).ConfigureAwait(false);
|
||||||
|
await s3.EnsureObjectExistsAsync(filesZipKey, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
return new PlondsPublishResult(
|
return new PlondsPublishResult(
|
||||||
ReleaseTag: releaseTag,
|
ReleaseTag: releaseTag,
|
||||||
@@ -94,7 +107,30 @@ public sealed class PlondsPublisher
|
|||||||
ChangedZipUrl: s3.BuildPublicUrl(changedZipKey),
|
ChangedZipUrl: s3.BuildPublicUrl(changedZipKey),
|
||||||
ChangedFolderKey: changedFolderKey,
|
ChangedFolderKey: changedFolderKey,
|
||||||
ChangedFolderUrl: s3.BuildPublicUrl(changedFolderKey),
|
ChangedFolderUrl: s3.BuildPublicUrl(changedFolderKey),
|
||||||
ChangedFileCount: changedFileCount);
|
FilesZipKey: filesZipKey,
|
||||||
|
FilesZipUrl: s3.BuildPublicUrl(filesZipKey),
|
||||||
|
FilesFolderKey: filesFolderKey,
|
||||||
|
FilesFolderUrl: s3.BuildPublicUrl(filesFolderKey),
|
||||||
|
ChangedFileCount: changedFileCount,
|
||||||
|
FilesFileCount: filesFileCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<int> UploadDirectoryAsync(
|
||||||
|
PlondsS3Client s3,
|
||||||
|
string sourceDirectory,
|
||||||
|
string destinationKeyPrefix,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var count = 0;
|
||||||
|
foreach (var filePath in Directory.EnumerateFiles(sourceDirectory, "*", SearchOption.AllDirectories).OrderBy(x => x, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var relativePath = PayloadUtilities.NormalizeRelativePath(Path.GetRelativePath(sourceDirectory, filePath));
|
||||||
|
var objectKey = $"{destinationKeyPrefix}/{relativePath}";
|
||||||
|
await s3.UploadFileAsync(new PlondsS3ObjectUpload(filePath, objectKey, ResolveContentType(filePath)), cancellationToken).ConfigureAwait(false);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PlondsManifest LoadManifest(string manifestPath)
|
private static PlondsManifest LoadManifest(string manifestPath)
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ public sealed record PlondsDownloadInfo(
|
|||||||
public sealed record PlondsGitHubDownloadInfo(
|
public sealed record PlondsGitHubDownloadInfo(
|
||||||
string ReleaseUrl,
|
string ReleaseUrl,
|
||||||
string ManifestUrl,
|
string ManifestUrl,
|
||||||
string ChangedZipUrl);
|
string ChangedZipUrl,
|
||||||
|
string FilesZipUrl);
|
||||||
|
|
||||||
public sealed record PlondsS3DownloadInfo(
|
public sealed record PlondsS3DownloadInfo(
|
||||||
string Bucket,
|
string Bucket,
|
||||||
@@ -21,4 +22,8 @@ public sealed record PlondsS3DownloadInfo(
|
|||||||
string ChangedZipKey,
|
string ChangedZipKey,
|
||||||
string ChangedZipUrl,
|
string ChangedZipUrl,
|
||||||
string ChangedFolderKey,
|
string ChangedFolderKey,
|
||||||
string ChangedFolderUrl);
|
string ChangedFolderUrl,
|
||||||
|
string FilesZipKey,
|
||||||
|
string FilesZipUrl,
|
||||||
|
string FilesFolderKey,
|
||||||
|
string FilesFolderUrl);
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ internal static class PlondsCli
|
|||||||
Repository: Require(options, "repository"),
|
Repository: Require(options, "repository"),
|
||||||
ManifestPath: Require(options, "manifest"),
|
ManifestPath: Require(options, "manifest"),
|
||||||
ChangedZipPath: Require(options, "changed-zip"),
|
ChangedZipPath: Require(options, "changed-zip"),
|
||||||
|
FilesZipPath: Require(options, "files-zip"),
|
||||||
WorkDir: Get(options, "work-dir", "plonds-publish-work") ?? "plonds-publish-work",
|
WorkDir: Get(options, "work-dir", "plonds-publish-work") ?? "plonds-publish-work",
|
||||||
S3KeyPrefix: Get(options, "s3-prefix", "lanmountain/update/plonds") ?? "lanmountain/update/plonds",
|
S3KeyPrefix: Get(options, "s3-prefix", "lanmountain/update/plonds") ?? "lanmountain/update/plonds",
|
||||||
S3: new PlondsS3ClientOptions(
|
S3: new PlondsS3ClientOptions(
|
||||||
@@ -119,7 +120,10 @@ internal static class PlondsCli
|
|||||||
Console.WriteLine($" Manifest: {result.ManifestUrl}");
|
Console.WriteLine($" Manifest: {result.ManifestUrl}");
|
||||||
Console.WriteLine($" ChangedZip: {result.ChangedZipUrl}");
|
Console.WriteLine($" ChangedZip: {result.ChangedZipUrl}");
|
||||||
Console.WriteLine($" ChangedFolder: {result.ChangedFolderUrl}");
|
Console.WriteLine($" ChangedFolder: {result.ChangedFolderUrl}");
|
||||||
|
Console.WriteLine($" FilesZip: {result.FilesZipUrl}");
|
||||||
|
Console.WriteLine($" FilesFolder: {result.FilesFolderUrl}");
|
||||||
Console.WriteLine($" ChangedFileCount: {result.ChangedFileCount}");
|
Console.WriteLine($" ChangedFileCount: {result.ChangedFileCount}");
|
||||||
|
Console.WriteLine($" FilesFileCount: {result.FilesFileCount}");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,6 +203,7 @@ internal static class PlondsCli
|
|||||||
Console.WriteLine(" --repository <owner/repo> GitHub repository");
|
Console.WriteLine(" --repository <owner/repo> GitHub repository");
|
||||||
Console.WriteLine(" --manifest <file> PLONDS.json path");
|
Console.WriteLine(" --manifest <file> PLONDS.json path");
|
||||||
Console.WriteLine(" --changed-zip <file> changed.zip path");
|
Console.WriteLine(" --changed-zip <file> changed.zip path");
|
||||||
|
Console.WriteLine(" --files-zip <file> Full files zip path");
|
||||||
Console.WriteLine(" --s3-endpoint <url> S3-compatible endpoint");
|
Console.WriteLine(" --s3-endpoint <url> S3-compatible endpoint");
|
||||||
Console.WriteLine(" --s3-region <region> S3 signing region");
|
Console.WriteLine(" --s3-region <region> S3 signing region");
|
||||||
Console.WriteLine(" --s3-bucket <bucket> S3 bucket");
|
Console.WriteLine(" --s3-bucket <bucket> S3 bucket");
|
||||||
|
|||||||
Reference in New Issue
Block a user