From 9bb56eb737c5d2835bb8645a471e3df7768fd6e2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 30 Mar 2026 23:05:46 +0000 Subject: [PATCH 1/3] Initial plan From 8e51b1825d7efd03f2e9a91fffe599fe01a4de42 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 30 Mar 2026 23:08:48 +0000 Subject: [PATCH 2/3] Use repo CreatedOn date instead of LastUpdatedOn for Delete action in cleanup command Fixes #2056: EOL annotation writes keep updating LastUpdatedOn on staging repos, preventing the 15-day age check from ever passing. Using CreatedOn ensures repos are deleted based on when they were originally created. Agent-Logs-Url: https://github.com/dotnet/docker-tools/sessions/0a39b8b7-2866-4759-ab63-7d2d91f58b4a Co-authored-by: lbussell <36081148+lbussell@users.noreply.github.com> --- src/ImageBuilder.Tests/CleanAcrImagesCommandTest.cs | 4 ++-- src/ImageBuilder/Commands/CleanAcrImagesCommand.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ImageBuilder.Tests/CleanAcrImagesCommandTest.cs b/src/ImageBuilder.Tests/CleanAcrImagesCommandTest.cs index d19719975..a0316bb26 100644 --- a/src/ImageBuilder.Tests/CleanAcrImagesCommandTest.cs +++ b/src/ImageBuilder.Tests/CleanAcrImagesCommandTest.cs @@ -34,14 +34,14 @@ public async Task StagingRepos() ContainerRepository nonPublicRepo1 = CreateContainerRepository( stagingRepo1Name, - CreateContainerRepositoryProperties(lastUpdatedOn: DateTimeOffset.Now.Subtract(TimeSpan.FromDays(14))), + CreateContainerRepositoryProperties(createdOn: DateTimeOffset.Now.Subtract(TimeSpan.FromDays(14))), [ CreateArtifactManifestProperties(repositoryName: stagingRepo1Name, digest: repo1Digest1) ]); ContainerRepository nonPublicRepo2 = CreateContainerRepository( stagingRepo2Name, - CreateContainerRepositoryProperties(lastUpdatedOn: DateTimeOffset.Now.Subtract(TimeSpan.FromDays(16))), + CreateContainerRepositoryProperties(createdOn: DateTimeOffset.Now.Subtract(TimeSpan.FromDays(16))), [ CreateArtifactManifestProperties(repositoryName: stagingRepo2Name, digest: repo2Digest1) ]); diff --git a/src/ImageBuilder/Commands/CleanAcrImagesCommand.cs b/src/ImageBuilder/Commands/CleanAcrImagesCommand.cs index 36904992e..4ed1aa81c 100644 --- a/src/ImageBuilder/Commands/CleanAcrImagesCommand.cs +++ b/src/ImageBuilder/Commands/CleanAcrImagesCommand.cs @@ -111,7 +111,7 @@ await ProcessManifestsAsync(acrClient, acrContentClient, deletedImages, deletedR manifest => Task.FromResult(IsExpired(manifest.LastUpdatedOn, Options.Age))); break; case CleanAcrImagesAction.Delete: - if (IsExpired(repository.GetProperties().Value.LastUpdatedOn, Options.Age)) + if (IsExpired(repository.GetProperties().Value.CreatedOn, Options.Age)) { await DeleteRepositoryAsync(acrClient, deletedRepos, repository); } From 8488aa49a74e40e2d66fbc2579d5f032fe8934c2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 30 Mar 2026 23:30:36 +0000 Subject: [PATCH 3/3] Revert CreatedOn change; add diagnostic logging to Delete action Reverts the CreatedOn change and instead adds structured logging to the Delete case that includes: created date, last updated date, manifest count, whether the repo is being deleted, and the reason why/why not. This will enable log analysis to determine the correct date field to use. Agent-Logs-Url: https://github.com/dotnet/docker-tools/sessions/9a845109-70e8-4747-a5d2-4f3ded9726e0 Co-authored-by: lbussell <36081148+lbussell@users.noreply.github.com> --- .../CleanAcrImagesCommandTest.cs | 4 ++-- src/ImageBuilder/Commands/CleanAcrImagesCommand.cs | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/ImageBuilder.Tests/CleanAcrImagesCommandTest.cs b/src/ImageBuilder.Tests/CleanAcrImagesCommandTest.cs index a0316bb26..d19719975 100644 --- a/src/ImageBuilder.Tests/CleanAcrImagesCommandTest.cs +++ b/src/ImageBuilder.Tests/CleanAcrImagesCommandTest.cs @@ -34,14 +34,14 @@ public async Task StagingRepos() ContainerRepository nonPublicRepo1 = CreateContainerRepository( stagingRepo1Name, - CreateContainerRepositoryProperties(createdOn: DateTimeOffset.Now.Subtract(TimeSpan.FromDays(14))), + CreateContainerRepositoryProperties(lastUpdatedOn: DateTimeOffset.Now.Subtract(TimeSpan.FromDays(14))), [ CreateArtifactManifestProperties(repositoryName: stagingRepo1Name, digest: repo1Digest1) ]); ContainerRepository nonPublicRepo2 = CreateContainerRepository( stagingRepo2Name, - CreateContainerRepositoryProperties(createdOn: DateTimeOffset.Now.Subtract(TimeSpan.FromDays(16))), + CreateContainerRepositoryProperties(lastUpdatedOn: DateTimeOffset.Now.Subtract(TimeSpan.FromDays(16))), [ CreateArtifactManifestProperties(repositoryName: stagingRepo2Name, digest: repo2Digest1) ]); diff --git a/src/ImageBuilder/Commands/CleanAcrImagesCommand.cs b/src/ImageBuilder/Commands/CleanAcrImagesCommand.cs index 4ed1aa81c..9d543b015 100644 --- a/src/ImageBuilder/Commands/CleanAcrImagesCommand.cs +++ b/src/ImageBuilder/Commands/CleanAcrImagesCommand.cs @@ -111,7 +111,19 @@ await ProcessManifestsAsync(acrClient, acrContentClient, deletedImages, deletedR manifest => Task.FromResult(IsExpired(manifest.LastUpdatedOn, Options.Age))); break; case CleanAcrImagesAction.Delete: - if (IsExpired(repository.GetProperties().Value.CreatedOn, Options.Age)) + ContainerRepositoryProperties repoProperties = repository.GetProperties().Value; + bool isDeleting = IsExpired(repoProperties.LastUpdatedOn, Options.Age); + _logger.LogInformation( + "Repository {RepositoryName}: CreatedOn={CreatedOn}, LastUpdatedOn={LastUpdatedOn}, ManifestCount={ManifestCount}, Deleting={Deleting}, Reason={Reason}", + repository.Name, + repoProperties.CreatedOn, + repoProperties.LastUpdatedOn, + repoProperties.ManifestCount, + isDeleting, + isDeleting + ? $"LastUpdatedOn is older than {Options.Age} days" + : $"LastUpdatedOn is within {Options.Age} days"); + if (isDeleting) { await DeleteRepositoryAsync(acrClient, deletedRepos, repository); }