mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 15:44:25 +08:00
changed.PLONDS启动
This commit is contained in:
@@ -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
|
||||
@@ -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"
|
||||
@@ -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:
|
||||
@@ -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`.
|
||||
@@ -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`
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -22,7 +22,6 @@ public enum UpdatePhase
|
||||
public enum UpdatePayloadKind
|
||||
{
|
||||
DeltaPlonds,
|
||||
DeltaLegacy,
|
||||
FullInstaller
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Plonds.Core.Publishing;
|
||||
|
||||
public sealed record DdssBuildOptions(
|
||||
public sealed record PlondsBuildOptions(
|
||||
string ReleaseTag,
|
||||
string AssetsDirectory,
|
||||
string OutputRoot,
|
||||
@@ -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),
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Plonds.Shared.Models;
|
||||
|
||||
public sealed record DdssMirrorEntry(
|
||||
public sealed record PlondsMirrorEntry(
|
||||
string Type,
|
||||
string Url);
|
||||
@@ -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>]");
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user