Skip to content

Commit c9cec29

Browse files
Add module prefix for Publish-PSResource cmdlet (#1694)
1 parent e9e8ecb commit c9cec29

File tree

5 files changed

+86
-41
lines changed

5 files changed

+86
-41
lines changed

src/code/ContainerRegistryServerAPICalls.cs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,15 +1129,18 @@ private static Collection<KeyValuePair<string, string>> GetDefaultHeaders(string
11291129
internal bool PushNupkgContainerRegistry(string psd1OrPs1File,
11301130
string outputNupkgDir,
11311131
string packageName,
1132+
string modulePrefix,
11321133
NuGetVersion packageVersion,
11331134
ResourceType resourceType,
1134-
Hashtable parsedMetadataHash,
1135-
Hashtable dependencies,
1135+
Hashtable parsedMetadataHash,
1136+
Hashtable dependencies,
11361137
out ErrorRecord errRecord)
11371138
{
11381139
_cmdletPassedIn.WriteDebug("In ContainerRegistryServerAPICalls::PushNupkgContainerRegistry()");
11391140
string fullNupkgFile = System.IO.Path.Combine(outputNupkgDir, packageName + "." + packageVersion.ToNormalizedString() + ".nupkg");
1140-
string packageNameLowercase = packageName.ToLower();
1141+
1142+
string pkgNameForUpload = string.IsNullOrEmpty(modulePrefix) ? packageName : modulePrefix + "/" + packageName;
1143+
string packageNameLowercase = pkgNameForUpload.ToLower();
11411144

11421145
// Get access token (includes refresh tokens)
11431146
_cmdletPassedIn.WriteVerbose($"Get access token for container registry server.");
@@ -1179,8 +1182,8 @@ internal bool PushNupkgContainerRegistry(string psd1OrPs1File,
11791182
return false;
11801183
}
11811184

1182-
// Create and upload manifest
1183-
TryCreateAndUploadManifest(fullNupkgFile, nupkgDigest, configDigest, packageName, resourceType, metadataJson, configFilePath, packageVersion, containerRegistryAccessToken, out errRecord);
1185+
// Create and upload manifest
1186+
TryCreateAndUploadManifest(fullNupkgFile, nupkgDigest, configDigest, packageName, modulePrefix, resourceType, metadataJson, configFilePath, packageVersion, containerRegistryAccessToken, out errRecord);
11841187
if (errRecord != null)
11851188
{
11861189
return false;
@@ -1195,7 +1198,7 @@ internal bool PushNupkgContainerRegistry(string psd1OrPs1File,
11951198
/// </summary>
11961199
private string UploadNupkgFile(string packageNameLowercase, string containerRegistryAccessToken, string fullNupkgFile, out ErrorRecord errRecord)
11971200
{
1198-
_cmdletPassedIn.WriteDebug("In ContainerRegistryServerAPICalls::UploadNupkgFile()");
1201+
_cmdletPassedIn.WriteDebug("In ContainerRegistryServerAPICalls::UploadNupkgFile()");
11991202
_cmdletPassedIn.WriteVerbose("Start uploading blob");
12001203
string nupkgDigest = string.Empty;
12011204
errRecord = null;
@@ -1349,6 +1352,7 @@ private bool TryCreateAndUploadManifest(string fullNupkgFile,
13491352
string nupkgDigest,
13501353
string configDigest,
13511354
string packageName,
1355+
string modulePrefix,
13521356
ResourceType resourceType,
13531357
string metadataJson,
13541358
string configFilePath,
@@ -1358,7 +1362,10 @@ private bool TryCreateAndUploadManifest(string fullNupkgFile,
13581362
{
13591363
_cmdletPassedIn.WriteDebug("In ContainerRegistryServerAPICalls::TryCreateAndUploadManifest()");
13601364
errRecord = null;
1361-
string packageNameLowercase = packageName.ToLower();
1365+
1366+
string pkgNameForUpload = string.IsNullOrEmpty(modulePrefix) ? packageName : modulePrefix + "/" + packageName;
1367+
string packageNameLowercase = pkgNameForUpload.ToLower();
1368+
13621369
FileInfo nupkgFile = new FileInfo(fullNupkgFile);
13631370
var fileSize = nupkgFile.Length;
13641371
var fileName = System.IO.Path.GetFileName(fullNupkgFile);

src/code/PublishHelper.cs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,12 @@ internal PublishHelper(PSCmdlet cmdlet, string path, string destinationPath, boo
7878
outputNupkgDir = destinationPath;
7979
}
8080

81-
internal PublishHelper(PSCmdlet cmdlet,
82-
PSCredential credential,
83-
string apiKey,
84-
string path,
85-
string destinationPath,
86-
bool skipModuleManifestValidate,
81+
internal PublishHelper(PSCmdlet cmdlet,
82+
PSCredential credential,
83+
string apiKey,
84+
string path,
85+
string destinationPath,
86+
bool skipModuleManifestValidate,
8787
CancellationToken cancellationToken,
8888
bool isNupkgPathSpecified)
8989
{
@@ -105,7 +105,7 @@ internal PublishHelper(PSCmdlet cmdlet,
105105

106106
#region Internal Methods
107107

108-
internal void PackResource()
108+
internal void PackResource()
109109
{
110110
// Returns the name of the file or the name of the directory, depending on path
111111
if (!_cmdletPassedIn.ShouldProcess(string.Format("'{0}' from the machine", resolvedPath)))
@@ -136,7 +136,7 @@ out string[] _
136136
}
137137

138138
parsedMetadata = scriptToPublish.ToHashtable();
139-
139+
140140
_pkgName = System.IO.Path.GetFileNameWithoutExtension(pathToScriptFileToPublish);
141141
}
142142
else
@@ -320,7 +320,7 @@ out string[] _
320320
}
321321
}
322322

323-
internal void PushResource(string Repository, bool SkipDependenciesCheck, NetworkCredential _networkCrendential)
323+
internal void PushResource(string Repository, string modulePrefix, bool SkipDependenciesCheck, NetworkCredential _networkCrendential)
324324
{
325325
try
326326
{
@@ -410,7 +410,8 @@ internal void PushResource(string Repository, bool SkipDependenciesCheck, Networ
410410
ContainerRegistryServerAPICalls containerRegistryServer = new ContainerRegistryServerAPICalls(repository, _cmdletPassedIn, _networkCredential, userAgentString);
411411

412412
var pkgMetadataFile = (resourceType == ResourceType.Script) ? pathToScriptFileToPublish : pathToModuleManifestToPublish;
413-
if (!containerRegistryServer.PushNupkgContainerRegistry(pkgMetadataFile, outputNupkgDir, _pkgName, _pkgVersion, resourceType, parsedMetadata, dependencies, out ErrorRecord pushNupkgContainerRegistryError))
413+
414+
if (!containerRegistryServer.PushNupkgContainerRegistry(pkgMetadataFile, outputNupkgDir, _pkgName, modulePrefix, _pkgVersion, resourceType, parsedMetadata, dependencies, out ErrorRecord pushNupkgContainerRegistryError))
414415
{
415416
_cmdletPassedIn.WriteError(pushNupkgContainerRegistryError);
416417
// exit out of processing
@@ -593,7 +594,7 @@ private bool PackNupkg(string outputDir, string outputNupkgDir, string nuspecFil
593594
private bool PushNupkg(string outputNupkgDir, string repoName, string repoUri, out ErrorRecord error)
594595
{
595596
_cmdletPassedIn.WriteDebug("In PublishPSResource::PushNupkg()");
596-
597+
597598
string fullNupkgFile;
598599
if (_isNupkgPathSpecified)
599600
{
@@ -1097,12 +1098,12 @@ private string CreateNuspec(
10971098
private Hashtable ParseRequiredModules(Hashtable parsedMetadataHash)
10981099
{
10991100
_cmdletPassedIn.WriteDebug("In PublishHelper::ParseRequiredModules()");
1100-
1101+
11011102
if (!parsedMetadataHash.ContainsKey("requiredmodules"))
11021103
{
11031104
return null;
11041105
}
1105-
1106+
11061107
LanguagePrimitives.TryConvertTo<object[]>(parsedMetadataHash["requiredmodules"], out object[] requiredModules);
11071108

11081109
// Required modules can be:
@@ -1136,7 +1137,7 @@ private Hashtable ParseRequiredModules(Hashtable parsedMetadataHash)
11361137
dependenciesHash.Add(moduleName, string.Empty);
11371138
}
11381139
}
1139-
1140+
11401141
var externalModuleDeps = parsedMetadataHash.ContainsKey("ExternalModuleDependencies") ?
11411142
parsedMetadataHash["ExternalModuleDependencies"] : null;
11421143

@@ -1157,7 +1158,7 @@ private Hashtable ParseRequiredModules(Hashtable parsedMetadataHash)
11571158
private bool CheckDependenciesExist(Hashtable dependencies, string repositoryName)
11581159
{
11591160
_cmdletPassedIn.WriteDebug("In PublishHelper::CheckDependenciesExist()");
1160-
1161+
11611162
// Check to see that all dependencies are in the repository
11621163
// Searches for each dependency in the repository the pkg is being pushed to,
11631164
// If the dependency is not there, error

src/code/PublishPSResource.cs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using Microsoft.PowerShell.PSResourceGet.UtilClasses;
55
using System;
6+
using System.Linq;
67
using System.Management.Automation;
78
using System.Net;
89
using System.Threading;
@@ -16,12 +17,13 @@ namespace Microsoft.PowerShell.PSResourceGet.Cmdlets
1617
"PSResource",
1718
SupportsShouldProcess = true)]
1819
[Alias("pbres")]
19-
public sealed class PublishPSResource : PSCmdlet
20+
public sealed class PublishPSResource : PSCmdlet, IDynamicParameters
2021
{
2122
#region Parameters
2223

2324
private const string PathParameterSet = "PathParameterSet";
2425
private const string NupkgPathParameterSet = "NupkgPathParameterSet";
26+
private ContainerRegistryDynamicParameters _pkgPrefix;
2527

2628
/// <summary>
2729
/// Specifies the API key that you want to use to publish a module to the online gallery.
@@ -117,6 +119,21 @@ public PSCredential ProxyCredential {
117119

118120
#endregion
119121

122+
#region DynamicParameters
123+
public object GetDynamicParameters()
124+
{
125+
PSRepositoryInfo repository = RepositorySettings.Read(new[] { Repository }, out string[] _).FirstOrDefault();
126+
if (repository is not null && repository.ApiVersion == PSRepositoryInfo.APIVersion.ContainerRegistry)
127+
{
128+
_pkgPrefix = new ContainerRegistryDynamicParameters();
129+
return _pkgPrefix;
130+
}
131+
132+
return null;
133+
}
134+
135+
#endregion
136+
120137
#region Members
121138

122139
private CancellationToken _cancellationToken;
@@ -145,10 +162,10 @@ protected override void BeginProcessing()
145162
RepositorySettings.CheckRepositoryStore();
146163

147164
_publishHelper = new PublishHelper(
148-
this,
149-
Credential,
150-
ApiKey,
151-
Path,
165+
this,
166+
Credential,
167+
ApiKey,
168+
Path,
152169
DestinationPath,
153170
SkipModuleManifestValidate,
154171
_cancellationToken,
@@ -169,10 +186,18 @@ protected override void EndProcessing()
169186
return;
170187
}
171188

172-
_publishHelper.PushResource(Repository, SkipDependenciesCheck, _networkCredential);
189+
string modulePrefix = _pkgPrefix?.ModulePrefix;
190+
191+
_publishHelper.PushResource(Repository, modulePrefix, SkipDependenciesCheck, _networkCredential);
173192
}
174193

175194
#endregion
176195

177196
}
197+
198+
public class ContainerRegistryDynamicParameters
199+
{
200+
[Parameter]
201+
public string ModulePrefix { get; set; }
202+
}
178203
}

src/code/ServerApiCall.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
using System.Text;
1111
using System.Runtime.ExceptionServices;
1212
using System.Management.Automation;
13-
using System;
1413

1514
namespace Microsoft.PowerShell.PSResourceGet.Cmdlets
1615
{
@@ -28,11 +27,11 @@ internal abstract class ServerApiCall : IServerAPICalls
2827
public ServerApiCall(PSRepositoryInfo repository, NetworkCredential networkCredential)
2928
{
3029
this.Repository = repository;
31-
30+
3231
HttpClientHandler handler = new HttpClientHandler();
3332
bool token = false;
3433

35-
if(networkCredential != null)
34+
if(networkCredential != null)
3635
{
3736
token = String.Equals("token", networkCredential.UserName) ? true : false;
3837
};
@@ -47,7 +46,7 @@ public ServerApiCall(PSRepositoryInfo repository, NetworkCredential networkCrede
4746
} else {
4847

4948
handler.Credentials = networkCredential;
50-
49+
5150
_sessionClient = new HttpClient(handler);
5251
};
5352
_sessionClient.Timeout = TimeSpan.FromMinutes(10);

test/PublishPSResourceTests/PublishPSResourceContainerRegistryServer.Tests.ps1

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,10 @@ Describe "Test Publish-PSResource" -tags 'CI' {
281281

282282
$results = Find-PSResource -Name $script:PublishModuleName -Repository $ACRRepoName -Version $version
283283
$results | Should -Not -BeNullOrEmpty
284-
$results[0].Name | Should -Be $script:PublishModuleName
285-
$results[0].Version | Should -Be $version
286-
$results[0].Dependencies.Name | Should -Be $dependencyName
287-
$results[0].Dependencies.VersionRange.MinVersion.ToString() | Should -Be $dependencyVersion
284+
$results[0].Name | Should -Be $script:PublishModuleName
285+
$results[0].Version | Should -Be $version
286+
$results[0].Dependencies.Name | Should -Be $dependencyName
287+
$results[0].Dependencies.VersionRange.MinVersion.ToString() | Should -Be $dependencyVersion
288288
}
289289

290290
It "Publish a module with multiple dependencies" {
@@ -296,18 +296,18 @@ Describe "Test Publish-PSResource" -tags 'CI' {
296296
# New-ModuleManifest requires that the module be installed before it can be added as a dependency
297297
Install-PSResource -Name $dependency1Name -Repository $ACRRepoName -TrustRepository -Verbose -Reinstall
298298
Install-PSResource -Name $dependency2Name -Version $dependency2Version -Repository $ACRRepoName -TrustRepository -Reinstall
299-
New-ModuleManifest -Path (Join-Path -Path $script:PublishModuleBase -ChildPath "$script:PublishModuleName.psd1") -ModuleVersion $version -Description "$script:PublishModuleName module" -RequiredModules @( $dependency1Name , @{ ModuleName = $dependency2Name; ModuleVersion = $dependency2Version })
299+
New-ModuleManifest -Path (Join-Path -Path $script:PublishModuleBase -ChildPath "$script:PublishModuleName.psd1") -ModuleVersion $version -Description "$script:PublishModuleName module" -RequiredModules @( $dependency1Name , @{ ModuleName = $dependency2Name; ModuleVersion = $dependency2Version })
300300

301301
Publish-PSResource -Path $script:PublishModuleBase -Repository $ACRRepoName
302302

303303
$results = Find-PSResource -Name $script:PublishModuleName -Repository $ACRRepoName -Version $version
304304
$results | Should -Not -BeNullOrEmpty
305-
$results[0].Name | Should -Be $script:PublishModuleName
306-
$results[0].Version | Should -Be $version
305+
$results[0].Name | Should -Be $script:PublishModuleName
306+
$results[0].Version | Should -Be $version
307307
$results[0].Dependencies.Name | Should -Be $dependency1Name, $dependency2Name
308-
$results[0].Dependencies.VersionRange.MinVersion.OriginalVersion.ToString() | Should -Be $dependency2Version
308+
$results[0].Dependencies.VersionRange.MinVersion.OriginalVersion.ToString() | Should -Be $dependency2Version
309309
}
310-
310+
311311
It "Publish a module and clean up properly when file in module is readonly" {
312312
$version = "13.0.0"
313313
New-ModuleManifest -Path (Join-Path -Path $script:PublishModuleBase -ChildPath "$script:PublishModuleName.psd1") -ModuleVersion $version -Description "$script:PublishModuleName module"
@@ -498,4 +498,17 @@ Describe "Test Publish-PSResource" -tags 'CI' {
498498

499499
{Publish-PSResource -Path $psm1Path -Repository $ACRRepoName -ErrorAction Stop} | Should -Throw -ErrorId "InvalidPublishPath,Microsoft.PowerShell.PSResourceGet.Cmdlets.PublishPSResource"
500500
}
501+
502+
It "Publish a module with -ModulePrefix" {
503+
$version = "1.0.0"
504+
$modulePrefix = "unlisted"
505+
New-ModuleManifest -Path (Join-Path -Path $script:PublishModuleBase -ChildPath "$script:PublishModuleName.psd1") -ModuleVersion $version -Description "$script:PublishModuleName module"
506+
507+
Publish-PSResource -Path $script:PublishModuleBase -Repository $ACRRepoName -ModulePrefix $modulePrefix
508+
509+
$results = Find-PSResource -Name "$modulePrefix/$script:PublishModuleName" -Repository $ACRRepoName
510+
$results | Should -Not -BeNullOrEmpty
511+
$results[0].Name | Should -Be $script:PublishModuleName
512+
$results[0].Version | Should -Be $version
513+
}
501514
}

0 commit comments

Comments
 (0)