diff --git a/src/code/ContainerRegistryServerAPICalls.cs b/src/code/ContainerRegistryServerAPICalls.cs index d9175c0b0..664471e7a 100644 --- a/src/code/ContainerRegistryServerAPICalls.cs +++ b/src/code/ContainerRegistryServerAPICalls.cs @@ -1129,12 +1129,13 @@ internal bool PushNupkgContainerRegistry( Hashtable dependencies, bool isNupkgPathSpecified, string originalNupkgPath, + string latestTag, out ErrorRecord errRecord) { _cmdletPassedIn.WriteDebug("In ContainerRegistryServerAPICalls::PushNupkgContainerRegistry()"); // if isNupkgPathSpecified, then we need to publish the original .nupkg file, as it may be signed - string fullNupkgFile = isNupkgPathSpecified ? originalNupkgPath : System.IO.Path.Combine(outputNupkgDir, packageName + "." + packageVersion.ToNormalizedString() + ".nupkg"); + string fullNupkgFile = isNupkgPathSpecified ? originalNupkgPath : System.IO.Path.Combine(outputNupkgDir, packageName + "." + packageVersion.ToNormalizedString() + ".nupkg"); string pkgNameForUpload = string.IsNullOrEmpty(modulePrefix) ? packageName : modulePrefix + "/" + packageName; string packageNameLowercase = pkgNameForUpload.ToLower(); @@ -1180,7 +1181,7 @@ internal bool PushNupkgContainerRegistry( } // Create and upload manifest - TryCreateAndUploadManifest(fullNupkgFile, nupkgDigest, configDigest, packageName, modulePrefix, resourceType, metadataJson, configFilePath, packageVersion, containerRegistryAccessToken, out errRecord); + TryCreateAndUploadManifest(fullNupkgFile, nupkgDigest, configDigest, packageName, modulePrefix, resourceType, metadataJson, configFilePath, packageVersion, latestTag, containerRegistryAccessToken, out errRecord); if (errRecord != null) { return false; @@ -1354,6 +1355,7 @@ private bool TryCreateAndUploadManifest(string fullNupkgFile, string metadataJson, string configFilePath, NuGetVersion pkgVersion, + string latestTag, string containerRegistryAccessToken, out ErrorRecord errRecord) { @@ -1371,15 +1373,24 @@ private bool TryCreateAndUploadManifest(string fullNupkgFile, _cmdletPassedIn.WriteVerbose("Create the manifest layer"); bool manifestCreated = false; + string currentTag = pkgVersion.OriginalVersion; try { - HttpResponseMessage manifestResponse = UploadManifest(packageNameLowercase, pkgVersion.OriginalVersion, configFilePath, true, containerRegistryAccessToken).Result; + HttpResponseMessage manifestResponse = UploadManifest(packageNameLowercase, currentTag, configFilePath, true, containerRegistryAccessToken).Result; manifestCreated = manifestResponse.IsSuccessStatusCode; + + if (!String.IsNullOrEmpty(latestTag)) + { + // we also want to publish this pkg version with latest/preview tag pointing to it + currentTag = latestTag; + HttpResponseMessage tagManifestResponse = UploadManifest(packageNameLowercase, latestTag, configFilePath, true, containerRegistryAccessToken).Result; + manifestCreated = manifestResponse.IsSuccessStatusCode; + } } catch (Exception e) { errRecord = new ErrorRecord( - new UploadBlobException($"Error occured while uploading package manifest to ContainerRegistry: {e.GetType()} '{e.Message}'", e), + new UploadBlobException($"Error occured while uploading package manifest with tag '{currentTag}' to ContainerRegistry: {e.GetType()} '{e.Message}'", e), "PackageManifestUploadError", ErrorCategory.InvalidResult, _cmdletPassedIn); diff --git a/src/code/PublishHelper.cs b/src/code/PublishHelper.cs index 66daea84e..1686d803b 100644 --- a/src/code/PublishHelper.cs +++ b/src/code/PublishHelper.cs @@ -53,6 +53,8 @@ internal enum CallerCmdlet private NetworkCredential _networkCredential; string userAgentString = UserAgentInfo.UserAgentString(); private bool _isNupkgPathSpecified = false; + private bool _isContainerRegistryLatest = false; + private bool _isContainerRegistryLatestPreview = false; private Hashtable dependencies; private Hashtable parsedMetadata; private PSCredential Credential; @@ -88,7 +90,9 @@ internal PublishHelper(PSCmdlet cmdlet, string destinationPath, bool skipModuleManifestValidate, CancellationToken cancellationToken, - bool isNupkgPathSpecified) + bool isNupkgPathSpecified, + bool isContainerRegistryLatest, + bool isContainerRegistryLatestPreview) { _callerCmdlet = CallerCmdlet.PublishPSResource; _cmdOperation = "Publish"; @@ -100,6 +104,8 @@ internal PublishHelper(PSCmdlet cmdlet, SkipModuleManifestValidate = skipModuleManifestValidate; _cancellationToken = cancellationToken; _isNupkgPathSpecified = isNupkgPathSpecified; + _isContainerRegistryLatest = isContainerRegistryLatest; + _isContainerRegistryLatestPreview = isContainerRegistryLatestPreview; outputDir = System.IO.Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString()); outputNupkgDir = System.IO.Path.Combine(outputDir, "nupkg"); } @@ -460,7 +466,13 @@ internal void PushResource(string Repository, string modulePrefix, bool SkipDepe } } - if (!containerRegistryServer.PushNupkgContainerRegistry(outputNupkgDir, _pkgName, modulePrefix, _pkgVersion, resourceType, parsedMetadata, dependencies, _isNupkgPathSpecified, Path, out ErrorRecord pushNupkgContainerRegistryError)) + string latestTag = String.Empty; + if (_isContainerRegistryLatest || _isContainerRegistryLatestPreview) + { + latestTag = _isContainerRegistryLatest ? "latest" : "preview"; + } + + if (!containerRegistryServer.PushNupkgContainerRegistry(outputNupkgDir, _pkgName, modulePrefix, _pkgVersion, resourceType, parsedMetadata, dependencies, _isNupkgPathSpecified, Path, latestTag, out ErrorRecord pushNupkgContainerRegistryError)) { _cmdletPassedIn.WriteError(pushNupkgContainerRegistryError); return; diff --git a/src/code/PublishPSResource.cs b/src/code/PublishPSResource.cs index 524e86ae1..b46cae215 100644 --- a/src/code/PublishPSResource.cs +++ b/src/code/PublishPSResource.cs @@ -3,6 +3,7 @@ using Microsoft.PowerShell.PSResourceGet.UtilClasses; using System; +using System.Diagnostics; using System.Linq; using System.Management.Automation; using System.Net; @@ -117,6 +118,12 @@ public PSCredential ProxyCredential { [ValidateNotNullOrEmpty] public string NupkgPath { get; set; } + [Parameter] + public SwitchParameter Latest { get; set; } + + [Parameter] + public SwitchParameter LatestPreview { get; set; } + #endregion #region DynamicParameters @@ -169,7 +176,9 @@ protected override void BeginProcessing() DestinationPath, SkipModuleManifestValidate, _cancellationToken, - _isNupkgPathSpecified); + _isNupkgPathSpecified, + Latest, + LatestPreview); _publishHelper.CheckAllParameterPaths(); }