Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- name: Verify workspace versions are aligned
run: ./scripts/check-version-sync.sh
- id: version
Expand All @@ -35,7 +35,7 @@ jobs:
name: Vendor Sync
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
submodules: true
- name: Verify surge-core vendor snapshot
Expand All @@ -46,23 +46,23 @@ jobs:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- run: rustup component add rustfmt
- run: cargo fmt --all -- --check

maintainability:
name: maintainability
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- name: Run maintainability guardrail
run: ./scripts/check-maintainability.sh

clippy:
name: clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
submodules: true
- uses: Swatinem/rust-cache@v2
Expand All @@ -76,7 +76,7 @@ jobs:
name: clippy strict
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
submodules: true
- uses: Swatinem/rust-cache@v2
Expand All @@ -90,7 +90,7 @@ jobs:
name: clippy pedantic (advisory)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
submodules: true
- uses: Swatinem/rust-cache@v2
Expand Down Expand Up @@ -121,7 +121,7 @@ jobs:
name: macOS
cache_key: macos-test
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
submodules: true
- uses: Swatinem/rust-cache@v2
Expand Down Expand Up @@ -181,7 +181,7 @@ jobs:
target/release/surge-installer-ui
target/release/surge-supervisor
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
submodules: true
- uses: actions/cache@v6
Expand Down Expand Up @@ -228,7 +228,7 @@ jobs:
run:
working-directory: dotnet
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
submodules: true
- uses: actions/setup-dotnet@v5
Expand Down
15 changes: 7 additions & 8 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ env:

permissions:
contents: write
packages: write

jobs:
validate-release:
Expand All @@ -24,7 +23,7 @@ jobs:
release_version: ${{ steps.validate.outputs.release_version }}
is_prerelease: ${{ steps.validate.outputs.is_prerelease }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}
fetch-depth: 0
Expand Down Expand Up @@ -124,7 +123,7 @@ jobs:
target/release/surge-installer-ui
target/release/surge-supervisor
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}
submodules: true
Expand Down Expand Up @@ -175,7 +174,7 @@ jobs:
run:
working-directory: dotnet
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}
submodules: true
Expand All @@ -189,8 +188,8 @@ jobs:
restore-keys: nuget-
- name: Pack
run: dotnet pack Surge.NET/Surge.NET.csproj --configuration Release -p:Version=${{ needs.validate-release.outputs.release_version }} --output ../nupkgs
- name: Push to GitHub Packages
run: dotnet nuget push ../nupkgs/*.nupkg --source https://nuget.pkg.github.com/fintermobilityas/index.json --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
- name: Push to NuGet
run: dotnet nuget push ../nupkgs/*.nupkg --source nuget.org --api-key ${{ secrets.PETERSUNDE_NUGET_ORG_API_KEY }} --skip-duplicate

publish-cargo-crates-io:
name: Publish Cargo (crates.io)
Expand All @@ -199,7 +198,7 @@ jobs:
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}
submodules: true
Expand Down Expand Up @@ -235,7 +234,7 @@ jobs:
needs: [validate-release, build-artifacts]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}

Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 16 additions & 10 deletions crates/surge-cli/src/commands/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use surge_core::error::{Result, SurgeError};
use surge_core::install::{self as core_install, InstallProfile};
use surge_core::installer_package::{
InstallerPackageAcquisition, ResolveInstallerPackageOptions, ResolvedInstallerPackage, install_artifact_cache_dir,
prune_install_artifact_cache_with_stats, resolve_installer_package, retained_artifacts_for_resolved_install_cache,
prune_install_artifact_cache, resolve_installer_package, retained_artifacts_for_install_cache_without_index,
};
use surge_core::platform::fs::make_executable;
use surge_core::platform::paths::default_install_root;
Expand Down Expand Up @@ -379,17 +379,23 @@ fn ensure_stage_cache_entry(
}

fn prune_setup_artifact_cache(install_root: &Path, package: &ResolvedPackage, manifest: &InstallerManifest) {
let Some(retained_artifacts) = retained_artifacts_for_resolved_install_cache(package, manifest) else {
return;
let owned_retained_artifacts;
let retained_artifacts = match package.retained_artifacts.as_ref() {
Some(retained_artifacts) => retained_artifacts,
None => match retained_artifacts_for_install_cache_without_index(manifest) {
Some(retained_artifacts) => {
owned_retained_artifacts = retained_artifacts;
&owned_retained_artifacts
}
None => return,
},
};
match prune_install_artifact_cache_with_stats(install_root, retained_artifacts.as_ref()) {
Ok(result) if result.pruned_artifact_count == 0 => {}
Ok(result) => {
match prune_install_artifact_cache(install_root, retained_artifacts) {
Ok(0) => {}
Ok(pruned) => {
logline::info(&format!(
"Pruned {} stale artifact cache entr{}; retained policy key count: {}.",
result.pruned_artifact_count,
if result.pruned_artifact_count == 1 { "y" } else { "ies" },
result.retained_policy_key_count
"Pruned {pruned} stale artifact cache entr{}.",
if pruned == 1 { "y" } else { "ies" }
));
}
Err(e) => {
Expand Down
37 changes: 0 additions & 37 deletions crates/surge-core/src/installer_package.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::borrow::Cow;
use std::collections::BTreeSet;
use std::path::{Path, PathBuf};

Expand Down Expand Up @@ -42,12 +41,6 @@ pub struct ResolvedInstallerPackage {
pub acquisition: InstallerPackageAcquisition,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct InstallArtifactCachePruneResult {
pub retained_policy_key_count: usize,
pub pruned_artifact_count: usize,
}

impl ResolvedInstallerPackage {
#[must_use]
pub fn path(&self) -> &Path {
Expand Down Expand Up @@ -183,36 +176,6 @@ pub fn prune_install_artifact_cache(install_root: &Path, retained_artifacts: &BT
prune_cached_artifacts(&install_artifact_cache_dir(install_root), retained_artifacts)
}

pub fn prune_install_artifact_cache_with_stats(
install_root: &Path,
retained_artifacts: &BTreeSet<String>,
) -> Result<InstallArtifactCachePruneResult> {
prune_install_artifact_cache_dir_with_stats(&install_artifact_cache_dir(install_root), retained_artifacts)
}

pub fn prune_install_artifact_cache_dir_with_stats(
artifact_cache_dir: &Path,
retained_artifacts: &BTreeSet<String>,
) -> Result<InstallArtifactCachePruneResult> {
let pruned_artifact_count = prune_cached_artifacts(artifact_cache_dir, retained_artifacts)?;
Ok(InstallArtifactCachePruneResult {
retained_policy_key_count: retained_artifacts.len(),
pruned_artifact_count,
})
}

#[must_use]
pub fn retained_artifacts_for_resolved_install_cache<'a>(
package: &'a ResolvedInstallerPackage,
manifest: &InstallerManifest,
) -> Option<Cow<'a, BTreeSet<String>>> {
if let Some(retained_artifacts) = &package.retained_artifacts {
Some(Cow::Borrowed(retained_artifacts))
} else {
retained_artifacts_for_install_cache_without_index(manifest).map(Cow::Owned)
}
}

#[must_use]
pub fn retained_artifacts_for_install_cache_without_index(manifest: &InstallerManifest) -> Option<BTreeSet<String>> {
retained_artifacts_for_cache_policy_without_index(
Expand Down
91 changes: 0 additions & 91 deletions crates/surge-core/src/update/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3523,97 +3523,6 @@ echo started > new-child-started
assert!(remaining.is_empty(), "none retention should prune all cached artifacts");
}

#[tokio::test]
async fn test_download_and_apply_latest_full_artifact_retention_prunes_old_fulls_and_deltas() {
let tmp = tempfile::tempdir().unwrap();
let store_root = tmp.path().join("store");
let install_root = tmp.path().join("install");
let app_id = "test-app";
std::fs::create_dir_all(&store_root).unwrap();
std::fs::create_dir_all(&install_root).unwrap();
let app_store = app_scoped_store_root(&store_root, app_id);

let current_app_dir = install_root.join("app");
std::fs::create_dir_all(&current_app_dir).unwrap();
std::fs::write(current_app_dir.join("payload.txt"), "old payload").unwrap();

let rid = current_rid();
let old_full_filename = format!("{app_id}-1.0.0-{rid}-full.tar.zst");
let old_delta_filename = format!("{app_id}-1.0.0-{rid}-delta.tar.zst");
let latest_full_filename = format!("{app_id}-1.1.0-{rid}-full.tar.zst");
let latest_full_path = app_store.join(&latest_full_filename);

let artifact_cache = install_root.join(".surge-cache").join("artifacts");
std::fs::create_dir_all(&artifact_cache).unwrap();
std::fs::write(artifact_cache.join(&old_full_filename), b"old full").unwrap();
std::fs::write(artifact_cache.join(&old_delta_filename), b"old delta").unwrap();

let mut packer = ArchivePacker::new(3).unwrap();
packer.add_buffer("payload.txt", b"new payload", 0o644).unwrap();
packer.finalize_to_file(&latest_full_path).unwrap();

let latest_full_size = std::fs::metadata(&latest_full_path).unwrap().len() as i64;
let latest_full_sha256 = sha256_hex_file(&latest_full_path).unwrap();
let os = current_os_label_for_tests();

let mut old_release = make_entry("1.0.0", "stable", &os, &rid);
old_release.full_filename = old_full_filename.clone();
old_release.deltas = Vec::new();
old_release.preferred_delta_id.clear();

let mut latest_release = make_entry("1.1.0", "stable", &os, &rid);
latest_release.full_filename = latest_full_filename.clone();
latest_release.full_size = latest_full_size;
latest_release.full_sha256 = latest_full_sha256;
latest_release.deltas = Vec::new();
latest_release.preferred_delta_id.clear();

let index = ReleaseIndex {
app_id: app_id.to_string(),
releases: vec![old_release, latest_release],
..ReleaseIndex::default()
};

write_app_scoped_release_index(&store_root, app_id, &index);

let ctx = Arc::new(Context::new());
ctx.set_storage(
StorageProvider::Filesystem,
store_root.to_str().unwrap(),
"",
"",
"",
"",
);

let mut manager = UpdateManager::new(ctx, app_id, "1.0.0", "stable", install_root.to_str().unwrap()).unwrap();
manager
.set_artifact_retention_policy(InstallArtifactCachePolicy {
retention: InstallArtifactCacheRetention::LatestFull,
keep_full_count: 1,
})
.unwrap();

let info = manager.check_for_updates().await.unwrap().unwrap();
manager
.download_and_apply(&info, None::<fn(ProgressInfo)>)
.await
.unwrap();

assert!(
artifact_cache.join(&latest_full_filename).is_file(),
"latest full should remain in the local artifact cache"
);
assert!(
!artifact_cache.join(&old_full_filename).exists(),
"old full should be pruned by latest_full retention"
);
assert!(
!artifact_cache.join(&old_delta_filename).exists(),
"old delta should be pruned by latest_full retention"
);
}

#[cfg(target_os = "linux")]
#[tokio::test]
async fn test_download_and_apply_full_installs_shortcuts() {
Expand Down
12 changes: 6 additions & 6 deletions crates/surge-core/src/update/manager/finalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ use crate::install::{
InstallProfile, RuntimeManifestMetadata, copy_persistent_assets, prune_version_snapshots,
storage_provider_manifest_name, write_runtime_manifest,
};
use crate::installer_package::prune_install_artifact_cache_dir_with_stats;
use crate::platform::fs::atomic_rename;
use crate::platform::shortcuts::install_shortcuts;
use crate::releases::artifact_cache::prune_cached_artifacts;
use crate::releases::manifest::decompress_release_index;
use crate::releases::restore::{
retained_artifacts_for_cache_policy, retained_artifacts_for_cache_policy_without_index,
Expand Down Expand Up @@ -247,12 +247,12 @@ where
retained_artifacts_for_cache_policy_without_index(manager.artifact_retention_policy, &latest.full_filename)
};
if let Some(retained_artifacts) = retained_artifacts {
match prune_install_artifact_cache_dir_with_stats(artifact_cache_dir, &retained_artifacts) {
Ok(result) if result.pruned_artifact_count == 0 => {}
Ok(result) => {
match prune_cached_artifacts(artifact_cache_dir, &retained_artifacts) {
Ok(0) => {}
Ok(pruned) => {
debug!(
pruned = result.pruned_artifact_count,
retained = result.retained_policy_key_count,
pruned,
retained = retained_artifacts.len(),
"Pruned stale local artifact cache entries"
);
}
Expand Down
Loading
Loading