changed.PLONDS启动

This commit is contained in:
lincube
2026-05-28 20:07:03 +08:00
parent 313d093257
commit a1cc0ee2bf
20 changed files with 85 additions and 179 deletions

View File

@@ -1,4 +1,4 @@
name: PLONDS
name: PLONDS Comparator
concurrency:
group: plonds-${{ github.event_name }}-${{ github.event.release.tag_name || github.event.inputs.tag || github.run_id }}
@@ -87,13 +87,11 @@ jobs:
env:
UPDATE_PRIVATE_KEY_PEM: ${{ secrets.UPDATE_PRIVATE_KEY_PEM }}
PLONDS_SIGNING_KEY: ${{ secrets.PLONDS_SIGNING_KEY }}
PDC_SIGNING_KEY: ${{ secrets.PDC_SIGNING_KEY }}
shell: bash
run: |
set -euo pipefail
KEY="${PLONDS_SIGNING_KEY:-}"
if [[ -z "$KEY" ]]; then KEY="${UPDATE_PRIVATE_KEY_PEM:-}"; fi
if [[ -z "$KEY" ]]; then KEY="${PDC_SIGNING_KEY:-}"; fi
if [[ -z "$KEY" ]]; then
echo "No signing key is configured."
exit 1

View File

@@ -1,4 +1,4 @@
name: DDSS Rollback
name: PLONDS Rollback
on:
workflow_dispatch:
@@ -26,7 +26,7 @@ jobs:
contents: read
concurrency:
group: ddss-rollback-${{ github.event.inputs.channel }}
group: plonds-rollback-${{ github.event.inputs.channel }}
cancel-in-progress: false
steps:
@@ -63,7 +63,7 @@ jobs:
echo "RELEASE_CHANNEL=${CHANNEL}" >> "$GITHUB_ENV"
echo "S3_PUBLIC_BASE_URL=${PUBLIC_BASE}" >> "$GITHUB_ENV"
echo "S3_BASE_URL=${PUBLIC_BASE}/releases/${TAG}/assets" >> "$GITHUB_ENV"
echo "DDSS_CHANNEL_POINTER_KEY=lanmountain/update/meta/channels/${CHANNEL}/ddss-latest.json" >> "$GITHUB_ENV"
echo "PLONDS_CHANNEL_POINTER_KEY=lanmountain/update/meta/channels/${CHANNEL}/plonds-latest.json" >> "$GITHUB_ENV"
- name: Validate rollback target assets
env:
@@ -77,7 +77,7 @@ jobs:
run: |
set -euo pipefail
for name in ddss.json ddss.json.sig; do
for name in plonds.json plonds.json.sig; do
key="lanmountain/update/releases/${RELEASE_TAG}/assets/${name}"
aws --endpoint-url "$S3_ENDPOINT" --region "$AWS_REGION" s3api head-object \
--bucket "$S3_BUCKET" \
@@ -90,10 +90,10 @@ jobs:
set -euo pipefail
mkdir -p rollback-output
pointer_file="rollback-output/ddss-latest.json"
pointer_file="rollback-output/plonds-latest.json"
manifest_url="${S3_BASE_URL}/ddss.json"
sig_url="${S3_BASE_URL}/ddss.json.sig"
manifest_url="${S3_BASE_URL}/plonds.json"
sig_url="${S3_BASE_URL}/plonds.json.sig"
version="${RELEASE_TAG#v}"
updated_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
@@ -125,22 +125,22 @@ jobs:
run: |
set -euo pipefail
pointer_file="rollback-output/ddss-latest.json"
pointer_file="rollback-output/plonds-latest.json"
aws --endpoint-url "$S3_ENDPOINT" --region "$AWS_REGION" s3api put-object \
--bucket "$S3_BUCKET" \
--key "$DDSS_CHANNEL_POINTER_KEY" \
--key "$PLONDS_CHANNEL_POINTER_KEY" \
--body "$pointer_file"
aws --endpoint-url "$S3_ENDPOINT" --region "$AWS_REGION" s3api head-object \
--bucket "$S3_BUCKET" \
--key "$DDSS_CHANNEL_POINTER_KEY" >/dev/null
--key "$PLONDS_CHANNEL_POINTER_KEY" >/dev/null
curl -fsSI "$S3_PUBLIC_BASE_URL/meta/channels/${RELEASE_CHANNEL}/ddss-latest.json" >/dev/null
curl -fsSI "$S3_PUBLIC_BASE_URL/meta/channels/${RELEASE_CHANNEL}/plonds-latest.json" >/dev/null
- name: Print rollback summary
shell: bash
run: |
set -euo pipefail
echo "Rolled back channel '${RELEASE_CHANNEL}' to '${RELEASE_TAG}'."
echo "Pointer: ${S3_PUBLIC_BASE_URL}/meta/channels/${RELEASE_CHANNEL}/ddss-latest.json"
echo "Pointer: ${S3_PUBLIC_BASE_URL}/meta/channels/${RELEASE_CHANNEL}/plonds-latest.json"

View File

@@ -1,13 +1,13 @@
name: DDSS
name: PLONDS Publisher
concurrency:
group: ddss-${{ github.event_name }}-${{ github.event.workflow_run.id || github.event.inputs.tag || github.run_id }}
group: plonds-${{ github.event_name }}-${{ github.event.workflow_run.id || github.event.inputs.tag || github.run_id }}
cancel-in-progress: false
on:
workflow_run:
workflows:
- PLONDS
- PLONDS Comparator
types:
- completed
workflow_dispatch:
@@ -61,7 +61,7 @@ jobs:
CHANNEL="stable"
fi
echo "RELEASE_CHANNEL=${CHANNEL}" >> "$GITHUB_ENV"
echo "DDSS_CHANNEL_POINTER_KEY=lanmountain/update/meta/channels/${CHANNEL}/ddss-latest.json" >> "$GITHUB_ENV"
echo "PLONDS_CHANNEL_POINTER_KEY=lanmountain/update/meta/channels/${CHANNEL}/plonds-latest.json" >> "$GITHUB_ENV"
PUBLIC_BASE="${{ vars.S3_PUBLIC_BASE_URL }}"
if [[ -z "$PUBLIC_BASE" ]]; then
PUBLIC_BASE="https://cn-nb1.rains3.com/lmdesktop/lanmountain/update"
@@ -80,13 +80,11 @@ jobs:
env:
UPDATE_PRIVATE_KEY_PEM: ${{ secrets.UPDATE_PRIVATE_KEY_PEM }}
PLONDS_SIGNING_KEY: ${{ secrets.PLONDS_SIGNING_KEY }}
PDC_SIGNING_KEY: ${{ secrets.PDC_SIGNING_KEY }}
shell: bash
run: |
set -euo pipefail
KEY="${PLONDS_SIGNING_KEY:-}"
if [[ -z "$KEY" ]]; then KEY="${UPDATE_PRIVATE_KEY_PEM:-}"; fi
if [[ -z "$KEY" ]]; then KEY="${PDC_SIGNING_KEY:-}"; fi
if [[ -z "$KEY" ]]; then
echo "No signing key is configured."
exit 1
@@ -141,7 +139,7 @@ jobs:
for file in release-assets/*; do
[[ -f "$file" ]] || continue
name="$(basename "$file")"
if [[ "$name" == "ddss.json" || "$name" == "ddss.json.sig" ]]; then
if [[ "$name" == "plonds.json" || "$name" == "plonds.json.sig" ]]; then
continue
fi
key="lanmountain/update/releases/${RELEASE_TAG}/assets/${name}"
@@ -211,21 +209,21 @@ jobs:
--metadata "sha256=$sha256"
done
- name: Build DDSS manifest
- name: Build PLONDS manifest
shell: bash
run: |
set -euo pipefail
mkdir -p ddss-output
mkdir -p plonds-output
dotnet run --project PenguinLogisticsOnlineNetworkDistributionSystem/src/Plonds.Tool/Plonds.Tool.csproj --configuration Release -- \
build-ddss \
build-plonds \
--release-tag "$RELEASE_TAG" \
--assets-dir release-assets \
--output-dir ddss-output \
--output-dir plonds-output \
--private-key "$UPDATE_PRIVATE_KEY_PATH" \
--repository "${{ github.repository }}" \
--s3-base-url "$S3_BASE_URL"
- name: Validate DDSS asset references in Rainyun S3
- name: Validate PLONDS asset references in Rainyun S3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_KEY }}
@@ -236,12 +234,12 @@ jobs:
shell: bash
run: |
set -euo pipefail
keys=$(jq -r '.assets[]?.mirrors[]?.url // empty' ddss-output/ddss.json \
keys=$(jq -r '.assets[]?.mirrors[]?.url // empty' plonds-output/plonds.json \
| sed -n 's#^.*/lanmountain/update/\(.*\)$#lanmountain/update/\1#p' \
| sort -u)
if [[ -z "$keys" ]]; then
echo "No S3-backed asset URLs found in ddss.json"
echo "No S3-backed asset URLs found in plonds.json"
exit 1
fi
@@ -252,15 +250,15 @@ jobs:
--key "$key" >/dev/null
done <<< "$keys"
- name: Upload DDSS manifest to release
- name: Upload PLONDS manifest to release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
gh release upload "$RELEASE_TAG" ddss-output/ddss.json ddss-output/ddss.json.sig --clobber
gh release upload "$RELEASE_TAG" plonds-output/plonds.json plonds-output/plonds.json.sig --clobber
- name: Upload DDSS manifest to Rainyun S3 staging
- name: Upload PLONDS manifest to Rainyun S3 staging
env:
AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_KEY }}
@@ -271,7 +269,7 @@ jobs:
shell: bash
run: |
set -euo pipefail
for file in ddss-output/ddss.json ddss-output/ddss.json.sig; do
for file in plonds-output/plonds.json plonds-output/plonds.json.sig; do
name="$(basename "$file")"
key="lanmountain/update/releases/${RELEASE_TAG}/assets/${name}"
sha256="$(sha256sum "$file" | awk '{print $1}')"
@@ -282,11 +280,11 @@ jobs:
--metadata "sha256=$sha256"
done
- name: Prepare DDSS channel pointer
- name: Prepare PLONDS channel pointer
shell: bash
run: |
set -euo pipefail
pointer_file="ddss-output/ddss-latest.json"
pointer_file="plonds-output/plonds-latest.json"
cat > "$pointer_file" <<'JSON'
{
"schemaVersion": 1,
@@ -301,8 +299,8 @@ jobs:
}
JSON
manifest_url="${S3_BASE_URL}/ddss.json"
sig_url="${S3_BASE_URL}/ddss.json.sig"
manifest_url="${S3_BASE_URL}/plonds.json"
sig_url="${S3_BASE_URL}/plonds.json.sig"
version="${RELEASE_TAG#v}"
updated_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
@@ -315,7 +313,7 @@ jobs:
jq -e . "$pointer_file" >/dev/null
- name: Atomically publish DDSS channel pointer
- name: Atomically publish PLONDS channel pointer
env:
AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_KEY }}
@@ -326,8 +324,8 @@ jobs:
shell: bash
run: |
set -euo pipefail
pointer_file="ddss-output/ddss-latest.json"
staging_key="lanmountain/update/releases/${RELEASE_TAG}/assets/ddss-latest.json"
pointer_file="plonds-output/plonds-latest.json"
staging_key="lanmountain/update/releases/${RELEASE_TAG}/assets/plonds-latest.json"
aws --endpoint-url "$S3_ENDPOINT" --region "$AWS_REGION" s3api put-object \
--bucket "$S3_BUCKET" \
@@ -336,14 +334,14 @@ jobs:
aws --endpoint-url "$S3_ENDPOINT" --region "$AWS_REGION" s3api put-object \
--bucket "$S3_BUCKET" \
--key "$DDSS_CHANNEL_POINTER_KEY" \
--key "$PLONDS_CHANNEL_POINTER_KEY" \
--body "$pointer_file"
aws --endpoint-url "$S3_ENDPOINT" --region "$AWS_REGION" s3api head-object \
--bucket "$S3_BUCKET" \
--key "$DDSS_CHANNEL_POINTER_KEY" >/dev/null
--key "$PLONDS_CHANNEL_POINTER_KEY" >/dev/null
curl -fsSI "$S3_PUBLIC_BASE_URL/meta/channels/${RELEASE_CHANNEL}/ddss-latest.json" >/dev/null
curl -fsSI "$S3_PUBLIC_BASE_URL/meta/channels/${RELEASE_CHANNEL}/plonds-latest.json" >/dev/null
- name: Verify Rainyun S3 PLONDS output
env:

View File

@@ -1,16 +0,0 @@
# Checklist
- [x] `release.yml` does not invoke Velopack.
- [x] `plonds-build.yml` uploads app payload artifacts and generates PloNDS delta/static outputs.
- [x] S3 output path is rooted at `lanmountain/update/` (no system version prefix).
- [x] CI workflow expects `repo/`, `meta/`, `manifests/`, and `installers/` outputs after a release run.
- [x] Host update source keeps compatibility (`pdc`/`stcn` normalize to active PloNDS source).
- [x] Host can persist PloNDS payload into launcher incoming directory.
- [x] Launcher can apply PloNDS FileMap payload with signature/hash verification.
- [x] Legacy signed `files.json + update.zip` path still works as compatibility fallback.
- [x] Launcher keeps rollback-capable deployments after successful update.
- [x] Manual rollback returns a structured failure when the snapshot source directory is missing.
- [ ] CI run attached proving all release matrix jobs pass.
- [x] N-1 -> N incremental update verified locally on Windows x64.
- [ ] N-1 -> N incremental update verified on Windows x86 and Linux x64.
- [x] Rollback regression tests attached in `LanMountainDesktop.Tests`.

View File

@@ -1,48 +0,0 @@
# PDC Incremental Update Migration
## Goal
Replace VeloPack-based incremental packaging with a unified PDC FileMap + object-repo pipeline, while keeping Launcher installation, rollback, and update orchestration ownership unchanged.
## Stage 1 (Completed)
- Release workflow removed VeloPack-based release packaging.
- Signed FileMap path was restored as an interim release mechanism.
- Host/Launcher fallback behavior stayed compatible with `files.json + files.json.sig + update.zip`.
## Stage 2 (Current Implementation Target)
- Use GitHub Actions PloNDS static publishing as the active incremental path.
- Keep `phainon.yml` for future PDCC parity, but do not rely on PDCC for the current release flow.
- Promote PloNDS-distributed FileMap/object-repo as the primary incremental path.
- Keep GitHub Release installers and metadata as parallel distribution.
- Keep Launcher state machine ownership (`.current/.partial/.destroy` + snapshots).
- Check updates in order: NS3/PloNDS static source, GitHub Release PloNDS assets, then GitHub full installer.
- S3 object root is fixed to `lanmountain/update/` with no update-system version prefix.
- Public object URLs come from `S3_PUBLIC_BASE_URL`; do not infer them from `S3_ENDPOINT` and `S3_BUCKET`.
Expected S3 layout:
- `lanmountain/update/repo/sha256/<hash-prefix>/<hash-object>`
- `lanmountain/update/meta/channels/<channel>/<platform>/latest.json`
- `lanmountain/update/meta/distributions/<distributionId>.json`
- `lanmountain/update/manifests/<distributionId>/plonds-filemap.json`
- `lanmountain/update/manifests/<distributionId>/plonds-filemap.json.sig`
- `lanmountain/update/installers/<platform>/<version>/*`
## Acceptance
- `release.yml` contains no Velopack steps; PloNDS static publishing is handled by `plonds-build.yml` and `ddss-publish.yml`.
- Release jobs keep building installers for Windows x64/x86, Linux x64, and macOS.
- PloNDS metadata + FileMap + object repo are published under `lanmountain/update/`.
- Host can consume the NS3/PloNDS static payload and fallback to GitHub when unavailable.
- Launcher can apply both:
- legacy signed `files.json + update.zip`
- PloNDS FileMap object-repo payload.
- Rollback semantics keep both automatic failure rollback and manual rollback after a successful update.
## Deprecated Notes
- The following interim outputs are compatibility-only (not the long-term primary path):
- `files-windows-x64.json` / `.sig` / `update-windows-x64.zip`
- `files-windows-x86.json` / `.sig` / `update-windows-x86.zip`
- `files-linux-x64.json` / `.sig` / `update-linux-x64.zip`

View File

@@ -1,21 +0,0 @@
# Tasks
- [x] Remove VeloPack packaging from release workflow.
- [x] Keep signed FileMap path as interim compatibility fallback.
- [x] Remove launcher/runtime Velopack branching.
- [x] Add `phainon.yml` for PDCC publish configuration.
- [ ] Add PDCC installation + publish steps in `release.yml` (deferred; active path is GitHub Actions PloNDS static publish).
- [x] Upload app payload artifacts for PloNDS delta generation in release build jobs.
- [x] Publish PloNDS metadata + sha256 object repo to S3 path root `lanmountain/update/`.
- [x] Mirror installers to `lanmountain/update/installers/<platform>/<version>/`.
- [x] Keep update source compatibility (`pdc`/`stcn` normalize to active PloNDS source).
- [x] Add PloNDS static payload model into host update check result.
- [x] Add host download path for PloNDS payload (`plonds-filemap.json` + signature + object repo).
- [x] Add launcher PloNDS FileMap apply path with rollback-compatible semantics.
- [x] Keep old `files.json + update.zip` path behind compatibility fallback.
- [x] Keep rollback deployment directories after successful apply and prune by bounded retention.
- [x] Return structured failure when manual rollback snapshot source is missing.
- [x] Verify static S3 layout, filemap/signature, distribution, latest pointer, and at least one object in CI workflows.
- [x] Add regression tests for PloNDS success rollback, hash-failure auto rollback, missing rollback source, static NS3 manifest, and manifest field mapping.
- [ ] Attach live CI run proving the full release matrix passes.
- [ ] Verify N-1 -> N incremental update on Windows x86 and Linux x64 in release artifacts.

View File

@@ -12,23 +12,23 @@ internal sealed class PendingUpdateDetector(
{
if (File.Exists(paths.PlondsFileMapPath) && File.Exists(paths.PlondsSignaturePath))
{
var pdcFileMapText = File.ReadAllText(paths.PlondsFileMapPath);
var pdcFileMap = JsonSerializer.Deserialize(pdcFileMapText, AppJsonContext.Default.PlondsFileMap);
if (pdcFileMap is null)
var plondsFileMapText = File.ReadAllText(paths.PlondsFileMapPath);
var plondsFileMap = JsonSerializer.Deserialize(plondsFileMapText, AppJsonContext.Default.PlondsFileMap);
if (plondsFileMap is null)
{
return UpdateEngineResults.Failed("update.check", "invalid_manifest", "plonds-filemap.json is invalid.");
}
var pdcVerified = signatureVerifier.Verify(
var plondsVerified = signatureVerifier.Verify(
paths.PlondsFileMapPath,
paths.PlondsSignaturePath,
UpdateEnginePaths.PlondsSignatureFileName);
if (!pdcVerified.Success)
if (!plondsVerified.Success)
{
return UpdateEngineResults.Failed("update.check", "signature_failed", pdcVerified.Message);
return UpdateEngineResults.Failed("update.check", "signature_failed", plondsVerified.Message);
}
var pdcMetadata = PlondsManifestParser.LoadMetadata(paths.PlondsUpdateMetadataPath);
var plondsMetadata = PlondsManifestParser.LoadMetadata(paths.PlondsUpdateMetadataPath);
return new LauncherResult
{
Success = true,
@@ -36,7 +36,7 @@ internal sealed class PendingUpdateDetector(
Code = "available",
Message = "Pending PLONDS update is available.",
CurrentVersion = deploymentLocator.GetCurrentVersion(),
TargetVersion = PlondsManifestParser.ResolveTargetVersion(pdcFileMap, pdcMetadata)
TargetVersion = PlondsManifestParser.ResolveTargetVersion(plondsFileMap, plondsMetadata)
};
}

View File

@@ -39,11 +39,11 @@ internal sealed class PlondsUpdateApplier(
return UpdateEngineResults.Failed("update.apply", "invalid_manifest", "No PLONDS file entries were found.");
}
var pdcMetadata = PlondsManifestParser.LoadMetadata(paths.PlondsUpdateMetadataPath);
var plondsMetadata = PlondsManifestParser.LoadMetadata(paths.PlondsUpdateMetadataPath);
var currentDeployment = deploymentLocator.FindCurrentDeploymentDirectory();
var currentVersion = deploymentLocator.GetCurrentVersion();
var sourceVersion = string.IsNullOrWhiteSpace(currentVersion) ? "0.0.0" : currentVersion;
var expectedSourceVersion = PlondsManifestParser.ResolveSourceVersion(fileMap, pdcMetadata);
var expectedSourceVersion = PlondsManifestParser.ResolveSourceVersion(fileMap, plondsMetadata);
if (!string.IsNullOrWhiteSpace(expectedSourceVersion) &&
!string.Equals(expectedSourceVersion, sourceVersion, StringComparison.OrdinalIgnoreCase))
{
@@ -53,7 +53,7 @@ internal sealed class PlondsUpdateApplier(
$"PLONDS update requires source version {expectedSourceVersion} but current is {sourceVersion}.");
}
var targetVersion = PlondsManifestParser.ResolveTargetVersion(fileMap, pdcMetadata);
var targetVersion = PlondsManifestParser.ResolveTargetVersion(fileMap, plondsMetadata);
if (string.IsNullOrWhiteSpace(targetVersion))
{
targetVersion = sourceVersion;

View File

@@ -15,7 +15,7 @@ public sealed record UpdateManifest(
IReadOnlyList<UpdateMirrorAsset>? InstallerMirrors,
IReadOnlyDictionary<string, string> Metadata)
{
public bool IsDelta => Kind is UpdatePayloadKind.DeltaPlonds or UpdatePayloadKind.DeltaLegacy;
public bool IsDelta => Kind is UpdatePayloadKind.DeltaPlonds;
public long EstimatedDeltaBytes
{

View File

@@ -22,7 +22,6 @@ public enum UpdatePhase
public enum UpdatePayloadKind
{
DeltaPlonds,
DeltaLegacy,
FullInstaller
}

View File

@@ -37,7 +37,7 @@ internal sealed class UpdateInstallGateway
return new InstallResult(false, lockError, false, lockErrorCode);
}
if (payloadKind is UpdatePayloadKind.DeltaPlonds or UpdatePayloadKind.DeltaLegacy)
if (payloadKind is UpdatePayloadKind.DeltaPlonds)
{
var launched = LaunchLauncherForApplyUpdate(launcherRoot);
if (!launched)
@@ -108,7 +108,7 @@ internal sealed class UpdateInstallGateway
return false;
}
var expectedKind = payloadKind is UpdatePayloadKind.DeltaLegacy or UpdatePayloadKind.DeltaPlonds ? "delta" : "full";
var expectedKind = payloadKind is UpdatePayloadKind.DeltaPlonds ? "delta" : "full";
if (!string.Equals(deploymentLock.Kind, expectedKind, StringComparison.OrdinalIgnoreCase))
{
errorCode = "lock_conflict";

View File

@@ -15,11 +15,7 @@ public static class UpdateSettingsValues
// NOTE: keep constant name for compatibility with existing call sites.
public const string DownloadSourcePlonds = "plonds-api";
public const string DownloadSourcePdc = DownloadSourcePlonds;
public const string DownloadSourceStcn = DownloadSourcePlonds;
public const string LegacyDownloadSourcePlonds = "pdc";
public const string LegacyDownloadSourcePdc = LegacyDownloadSourcePlonds;
public const string LegacyDownloadSourceStcn = "stcn";
public const string DownloadSourceGitHub = "github";
public const string DownloadSourceGhProxy = "gh-proxy";
public const string PlondsStaticBaseUrlEnvironmentVariable = "LANMOUNTAIN_UPDATE_BASE_URL";
@@ -62,12 +58,12 @@ public static class UpdateSettingsValues
public static string NormalizeDownloadSource(string? value)
{
if (string.Equals(value, LegacyDownloadSourcePlonds, StringComparison.OrdinalIgnoreCase))
if (string.Equals(value, "pdc", StringComparison.OrdinalIgnoreCase))
{
return DownloadSourcePlonds;
}
if (string.Equals(value, LegacyDownloadSourceStcn, StringComparison.OrdinalIgnoreCase))
if (string.Equals(value, "stcn", StringComparison.OrdinalIgnoreCase))
{
return DownloadSourcePlonds;
}

View File

@@ -99,7 +99,7 @@ public sealed partial class UpdateSettingsViewModel : ViewModelBase, IDisposable
[ObservableProperty] private bool _forceReinstall;
[ObservableProperty] private string _selectedUpdateChannelValue = UpdateSettingsValues.ChannelStable;
[ObservableProperty] private string _selectedUpdateSourceValue = UpdateSettingsValues.DownloadSourcePdc;
[ObservableProperty] private string _selectedUpdateSourceValue = UpdateSettingsValues.DownloadSourcePlonds;
[ObservableProperty] private string _selectedUpdateModeValue = UpdateSettingsValues.ModeSilentDownload;
[ObservableProperty] private double _downloadThreadsSliderValue = UpdateSettingsValues.DefaultDownloadThreads;
@@ -220,7 +220,7 @@ public sealed partial class UpdateSettingsViewModel : ViewModelBase, IDisposable
LatestVersionText = report.LatestVersion ?? string.Empty;
PublishedAtText = report.PublishedAt?.ToLocalTime().ToString("g", CultureInfo.CurrentCulture) ?? string.Empty;
UpdateTypeText = GetUpdateTypeText(report.PayloadKind);
IsDeltaUpdate = report.PayloadKind is UpdatePayloadKind.DeltaPlonds or UpdatePayloadKind.DeltaLegacy;
IsDeltaUpdate = report.PayloadKind is UpdatePayloadKind.DeltaPlonds;
StatusMessage = report.LatestVersion is null
? GetUpdateAvailableStatusText(string.Empty)
: string.Format(CultureInfo.CurrentCulture, L("settings.update.status_available_format", "New version {0} is available. Click Download and Install."), report.LatestVersion);
@@ -627,7 +627,7 @@ public sealed partial class UpdateSettingsViewModel : ViewModelBase, IDisposable
return payloadKind switch
{
UpdatePayloadKind.DeltaPlonds or UpdatePayloadKind.DeltaLegacy => L("settings.update.type_delta", "Incremental Update"),
UpdatePayloadKind.DeltaPlonds => L("settings.update.type_delta", "Incremental Update"),
UpdatePayloadKind.FullInstaller => L("settings.update.type_reinstall", "Reinstall"),
_ => string.Empty
};

View File

@@ -1,6 +1,6 @@
namespace Plonds.Core.Publishing;
public sealed record DdssBuildOptions(
public sealed record PlondsBuildOptions(
string ReleaseTag,
string AssetsDirectory,
string OutputRoot,

View File

@@ -3,18 +3,18 @@ using Plonds.Shared.Models;
namespace Plonds.Core.Publishing;
public sealed class DdssManifestBuilder
public sealed class PlondsManifestBuilder
{
private readonly RsaFileSigner _signer = new();
public string Build(DdssBuildOptions options)
public string Build(PlondsBuildOptions options)
{
ArgumentNullException.ThrowIfNull(options);
var assetsDirectory = Path.GetFullPath(options.AssetsDirectory);
if (!Directory.Exists(assetsDirectory))
{
throw new DirectoryNotFoundException($"DDSS assets directory not found: {assetsDirectory}");
throw new DirectoryNotFoundException($"PLONDS assets directory not found: {assetsDirectory}");
}
var assetEntries = Directory
@@ -22,14 +22,14 @@ public sealed class DdssManifestBuilder
.Where(static path =>
{
var name = Path.GetFileName(path);
return !name.Equals("ddss.json", StringComparison.OrdinalIgnoreCase)
&& !name.Equals("ddss.json.sig", StringComparison.OrdinalIgnoreCase);
return !name.Equals("plonds.json", StringComparison.OrdinalIgnoreCase)
&& !name.Equals("plonds.json.sig", StringComparison.OrdinalIgnoreCase);
})
.OrderBy(static path => Path.GetFileName(path), StringComparer.OrdinalIgnoreCase)
.Select(path => BuildAssetEntry(path, options.Repository, options.ReleaseTag, options.S3BaseUrl))
.ToArray();
var manifest = new DdssManifest(
var manifest = new PlondsManifest(
FormatVersion: "1.0",
ReleaseTag: options.ReleaseTag,
GeneratedAt: DateTimeOffset.UtcNow,
@@ -37,28 +37,28 @@ public sealed class DdssManifestBuilder
var outputRoot = Path.GetFullPath(options.OutputRoot);
Directory.CreateDirectory(outputRoot);
var manifestPath = Path.Combine(outputRoot, "ddss.json");
var manifestPath = Path.Combine(outputRoot, "plonds.json");
PayloadUtilities.WriteJson(manifestPath, manifest);
_signer.SignFile(manifestPath, options.PrivateKeyPath, manifestPath + ".sig");
return manifestPath;
}
private static DdssAssetEntry BuildAssetEntry(string assetPath, string repository, string releaseTag, string? s3BaseUrl)
private static PlondsAssetEntry BuildAssetEntry(string assetPath, string repository, string releaseTag, string? s3BaseUrl)
{
var fileName = Path.GetFileName(assetPath);
var mirrors = new List<DdssMirrorEntry>
var mirrors = new List<PlondsMirrorEntry>
{
new("github", $"https://github.com/{repository}/releases/download/{releaseTag}/{Uri.EscapeDataString(fileName)}")
};
if (!string.IsNullOrWhiteSpace(s3BaseUrl))
{
mirrors.Add(new DdssMirrorEntry(
mirrors.Add(new PlondsMirrorEntry(
"s3",
$"{s3BaseUrl.TrimEnd('/')}/{Uri.EscapeDataString(fileName)}"));
}
return new DdssAssetEntry(
return new PlondsAssetEntry(
AssetId: fileName,
FileName: fileName,
Sha256: PayloadUtilities.ComputeSha256(assetPath),

View File

@@ -1,8 +1,8 @@
namespace Plonds.Shared.Models;
public sealed record DdssAssetEntry(
public sealed record PlondsAssetEntry(
string AssetId,
string FileName,
string Sha256,
long Size,
IReadOnlyList<DdssMirrorEntry> Mirrors);
IReadOnlyList<PlondsMirrorEntry> Mirrors);

View File

@@ -1,7 +1,7 @@
namespace Plonds.Shared.Models;
public sealed record DdssManifest(
public sealed record PlondsManifest(
string FormatVersion,
string ReleaseTag,
DateTimeOffset GeneratedAt,
IReadOnlyList<DdssAssetEntry> Assets);
IReadOnlyList<PlondsAssetEntry> Assets);

View File

@@ -1,5 +1,5 @@
namespace Plonds.Shared.Models;
public sealed record DdssMirrorEntry(
public sealed record PlondsMirrorEntry(
string Type,
string Url);

View File

@@ -38,8 +38,8 @@ internal static class PlondsCli
case "build-index":
RunBuildIndex(options);
return Task.FromResult(0);
case "build-ddss":
RunBuildDdss(options);
case "build-plonds":
RunBuildPlonds(options);
return Task.FromResult(0);
default:
Console.Error.WriteLine($"Unknown command: {command}");
@@ -157,10 +157,10 @@ internal static class PlondsCli
Console.WriteLine(manifestPath);
}
private static void RunBuildDdss(Dictionary<string, string> options)
private static void RunBuildPlonds(Dictionary<string, string> options)
{
var builder = new DdssManifestBuilder();
var manifestPath = builder.Build(new DdssBuildOptions(
var builder = new PlondsManifestBuilder();
var manifestPath = builder.Build(new PlondsBuildOptions(
ReleaseTag: Require(options, "release-tag"),
AssetsDirectory: Require(options, "assets-dir"),
OutputRoot: Require(options, "output-dir"),
@@ -215,7 +215,7 @@ internal static class PlondsCli
Console.WriteLine(" pack-payload --source-dir <dir> --output-zip <file>");
Console.WriteLine(" build-delta --platform <platform> --current-version <v> --current-tag <tag> --current-zip <file> --output-dir <dir> --private-key <pem> [--baseline-tag <tag>] [--baseline-version <v>] [--baseline-zip <file>] [--is-full-payload] [--static-output-dir <dir>] [--update-base-url <url>]");
Console.WriteLine(" build-index --release-tag <tag> --version <v> --platform-summaries-dir <dir> --output-dir <dir> --private-key <pem> [--channel <channel>]");
Console.WriteLine(" build-ddss --release-tag <tag> --assets-dir <dir> --output-dir <dir> --private-key <pem> --repository <owner/repo> [--s3-base-url <url>]");
Console.WriteLine(" build-plonds --release-tag <tag> --assets-dir <dir> --output-dir <dir> --private-key <pem> --repository <owner/repo> [--s3-base-url <url>]");
Console.WriteLine(" sign --manifest <file> --private-key <pem> [--output <file>]");
Console.WriteLine(" generate --current-version <v> --current-dir <dir> --platform <platform> --output-dir <dir> [--previous-version <v>] [--previous-dir <dir>]");
Console.WriteLine(" publish --version <v> --app-artifacts-root <dir> --installer-artifacts-root <dir> --output-dir <dir> --private-key <pem> [--baseline-root <dir>]");

View File

@@ -31,7 +31,7 @@
| Category | Count | Files |
|----------|-------|-------|
| CI/CD Workflows | 3 | `ddss-publish.yml`, `ddss-rollback.yml`, `plonds-build.yml` |
| CI/CD Workflows | 3 | `plonds-uploader.yml`, `plonds-rollback.yml`, `plonds-comparator.yml` |
| Shared Contracts | 3 | `DeploymentLock.cs`, `UpdatePaths.cs`, `UpdateState.cs` |
| Launcher | 2 | `AppJsonContext.cs`, `UpdateModels.cs` |
| Services | 7 | `UpdateEngineService.cs`, `DeploymentLockService.cs`, `UpdateDownloadEngine.cs`, `UpdateInstallGateway.cs`, `UpdateOrchestrator.cs`, `UpdateWorkflowService.cs`, `WindowPassthroughService.cs` |
@@ -49,7 +49,7 @@
### 1. CI/CD Workflows Enhancement
#### `.github/workflows/ddss-publish.yml` (+106 lines)
#### `.github/workflows/plonds-uploader.yml` (+106 lines)
**Purpose:** Enhanced deployment publishing workflow
**Key Changes:**
@@ -58,7 +58,7 @@
- Added atomic channel pointer publishing
- Improved deployment pipeline reliability
#### `.github/workflows/ddss-rollback.yml` (+146 lines) — **NEW**
#### `.github/workflows/plonds-rollback.yml` (+146 lines) — **NEW**
**Purpose:** Automated rollback workflow
**Key Features:**
@@ -66,7 +66,7 @@
- Emergency deployment recovery
- Version rollback automation
#### `.github/workflows/plonds-build.yml` (+5 lines)
#### `.github/workflows/plonds-comparator.yml` (+5 lines)
**Changes:**
- Adjusted build concurrency settings
- Updated release event triggers