private async Task SaveTagInfoToImageInfoFileAsync(DateTime createdDate, ImageArtifactDetails imageArtifactDetails) { _loggerService.WriteSubheading("SETTING TAG INFO"); IEnumerable <ImageData> images = imageArtifactDetails.Repos .SelectMany(repo => repo.Images) .Where(image => image.Manifest != null); await Parallel.ForEachAsync(images, async (image, cancellationToken) => { image.Manifest.Created = createdDate; TagInfo sharedTag = image.ManifestImage.SharedTags.First(); image.Manifest.Digest = DockerHelper.GetDigestString( image.ManifestRepo.FullModelName, await _manifestToolService.GetManifestDigestShaAsync( sharedTag.FullyQualifiedName, Options.CredentialsOptions, Options.IsDryRun)); IEnumerable <(string Repo, string Tag)> syndicatedRepresentativeSharedTags = image.ManifestImage.SharedTags .Where(tag => tag.SyndicatedRepo is not null) .GroupBy(tag => tag.SyndicatedRepo) .Select(group => (group.Key, group.First().SyndicatedDestinationTags.First())) .Cast <(string Repo, string Tag)>() .OrderBy(obj => obj.Repo) .ThenBy(obj => obj.Tag); foreach ((string Repo, string Tag)syndicatedSharedTag in syndicatedRepresentativeSharedTags) { string digest = DockerHelper.GetDigestString( DockerHelper.GetImageName(Manifest.Model.Registry, syndicatedSharedTag.Repo), await _manifestToolService.GetManifestDigestShaAsync( DockerHelper.GetImageName(Manifest.Registry, Options.RepoPrefix + syndicatedSharedTag.Repo, syndicatedSharedTag.Tag), Options.CredentialsOptions, Options.IsDryRun)); image.Manifest.SyndicatedDigests.Add(digest); } }); string imageInfoString = JsonHelper.SerializeObject(imageArtifactDetails); File.WriteAllText(Options.ImageInfoPath, imageInfoString); }
private void SetPlatformDataDigest(PlatformData platform, string tag) { // The digest of an image that is pushed to ACR is guaranteed to be the same when transferred to MCR. string digest = _imageDigestCache.GetImageDigest(tag, Options.IsDryRun); if (digest != null) { digest = DockerHelper.GetDigestString(platform.PlatformInfo.FullRepoModelName, DockerHelper.GetDigestSha(digest)); } if (platform.Digest != null && platform.Digest != digest) { // Pushing the same image with different tags should result in the same digest being output throw new InvalidOperationException( $"Tag '{tag}' was pushed with a resulting digest value that differs from the corresponding image's digest value." + Environment.NewLine + $"\tDigest value from image info: {platform.Digest}{Environment.NewLine}" + $"\tDigest value retrieved from query: {digest}"); } platform.Digest = digest; }
private void SaveTagInfoToImageInfoFile(DateTime createdDate, ImageArtifactDetails imageArtifactDetails) { _loggerService.WriteSubheading("SETTING TAG INFO"); IEnumerable <ImageData> images = imageArtifactDetails.Repos .SelectMany(repo => repo.Images) .Where(image => image.Manifest != null); Parallel.ForEach(images, image => { image.Manifest.Created = createdDate; TagInfo sharedTag = image.ManifestImage.SharedTags.First(); image.Manifest.Digest = DockerHelper.GetDigestString( image.ManifestRepo.FullModelName, _manifestToolService.GetManifestDigestSha( ManifestMediaType.ManifestList, sharedTag.FullyQualifiedName, Options.IsDryRun)); }); string imageInfoString = JsonHelper.SerializeObject(imageArtifactDetails); File.WriteAllText(Options.ImageInfoPath, imageInfoString); }
private List <string> GetPathsToRebuild( IEnumerable <PlatformInfo> allPlatforms, PlatformInfo platform, RepoData repoData) { bool foundImageInfo = false; List <string> pathsToRebuild = new List <string>(); void processPlatformWithMissingImageInfo(PlatformInfo platform) { _loggerService.WriteMessage( $"WARNING: Image info not found for '{platform.DockerfilePath}'. Adding path to build to be queued anyway."); IEnumerable <PlatformInfo> dependentPlatforms = platform.GetDependencyGraph(allPlatforms); pathsToRebuild.AddRange(dependentPlatforms.Select(p => p.Model.Dockerfile)); } if (repoData == null || repoData.Images == null) { processPlatformWithMissingImageInfo(platform); return(pathsToRebuild); } foreach (ImageData imageData in repoData.Images) { PlatformData platformData = imageData.Platforms .FirstOrDefault(platformData => platformData.PlatformInfo == platform); if (platformData != null) { foundImageInfo = true; string fromImage = platform.FinalStageFromImage; string currentDigest; currentDigest = LockHelper.DoubleCheckedLockLookup(_imageDigestsLock, _imageDigests, fromImage, () => { string digest = _manifestToolService.GetManifestDigestSha(ManifestMediaType.Any, fromImage, Options.IsDryRun); return(DockerHelper.GetDigestString(DockerHelper.GetRepo(fromImage), digest)); }); bool rebuildImage = platformData.BaseImageDigest != currentDigest; _loggerService.WriteMessage( $"Checking base image '{fromImage}' from '{platform.DockerfilePath}'{Environment.NewLine}" + $"\tLast build digest: {platformData.BaseImageDigest}{Environment.NewLine}" + $"\tCurrent digest: {currentDigest}{Environment.NewLine}" + $"\tImage is up-to-date: {!rebuildImage}{Environment.NewLine}"); if (rebuildImage) { IEnumerable <PlatformInfo> dependentPlatforms = platform.GetDependencyGraph(allPlatforms); pathsToRebuild.AddRange(dependentPlatforms.Select(p => p.Model.Dockerfile)); } break; } } if (!foundImageInfo) { processPlatformWithMissingImageInfo(platform); } return(pathsToRebuild); }