@@ -68,6 +68,10 @@ public class JoinVerticals : Microsoft.Build.Utilities.Task
6868 private const string _packageElementName = "Package" ;
6969 private const string _blobElementName = "Blob" ;
7070 private const string _idAttribute = "Id" ;
71+ private const string _visibilityAttribute = "Visibility" ;
72+ private const string _externalVisibility = "External" ;
73+ private const string _internalVisibility = "Internal" ;
74+ private const string _verticalVisibility = "Vertical" ;
7175 private const string _verticalNameAttribute = "VerticalName" ;
7276 private const string _artifactNameSuffix = "_Artifacts" ;
7377 private const string _assetsFolderName = "assets" ;
@@ -110,7 +114,7 @@ private async Task ExecuteAsync()
110114
111115 using var clientThrottle = new SemaphoreSlim ( 16 , 16 ) ;
112116 List < Task > downloadTasks = new ( ) ;
113-
117+
114118 foreach ( XDocument verticalManifest in verticalManifests )
115119 {
116120 string verticalName = GetRequiredRootAttribute ( verticalManifest , _verticalNameAttribute ) ;
@@ -188,28 +192,28 @@ private async Task DownloadArtifactFiles(
188192
189193 await Task . WhenAll ( fileNamesToDownload . Select ( async fileName =>
190194 await DownloadFileFromArtifact (
191- filesInformation ,
192- artifactName ,
193- azureDevOpsClient ,
194- buildId ,
195- fileName ,
196- outputDirectory ,
195+ filesInformation ,
196+ artifactName ,
197+ azureDevOpsClient ,
198+ buildId ,
199+ fileName ,
200+ outputDirectory ,
197201 clientThrottle ) ) ) ;
198202 }
199203
200204 private async Task DownloadFileFromArtifact (
201- ArtifactFiles artifactFilesMetadata ,
202- string azureDevOpsArtifact ,
203- AzureDevOpsClient azureDevOpsClient ,
204- string buildId ,
205- string manifestFile ,
205+ ArtifactFiles artifactFilesMetadata ,
206+ string azureDevOpsArtifact ,
207+ AzureDevOpsClient azureDevOpsClient ,
208+ string buildId ,
209+ string manifestFile ,
206210 string destinationDirectory ,
207211 SemaphoreSlim clientThrottle )
208212 {
209213 try
210214 {
211215 await clientThrottle . WaitAsync ( ) ;
212-
216+
213217 ArtifactItem fileItem ;
214218
215219 var matchingFilePaths = artifactFilesMetadata . Items . Where ( f => Path . GetFileName ( f . Path ) == Path . GetFileName ( manifestFile ) ) ;
@@ -260,7 +264,7 @@ private async Task DownloadFileFromArtifact(
260264 }
261265
262266 /// <summary>
263- /// Copy all files from the source directory to the destination directory,
267+ /// Copy all files from the source directory to the destination directory,
264268 /// in a flat layout
265269 /// </summary>
266270 private void CopyMainVerticalAssets ( string sourceDirectory , string destinationDirectory )
@@ -272,7 +276,7 @@ private void CopyMainVerticalAssets(string sourceDirectory, string destinationDi
272276 Directory . CreateDirectory ( destinationDirectory ) ;
273277 }
274278
275- foreach ( var sourceFile in sourceFiles )
279+ foreach ( var sourceFile in sourceFiles )
276280 {
277281 string destinationFilePath = Path . Combine ( destinationDirectory , Path . GetFileName ( sourceFile ) ) ;
278282
@@ -291,11 +295,35 @@ private List<string> AddMissingElements(Dictionary<string, AddedElement> addedAr
291295
292296 string verticalName = verticalManifest . Root ! . Attribute ( _verticalNameAttribute ) ! . Value ;
293297
294- foreach ( XElement artifactElement in verticalManifest . Descendants ( elementName ) )
298+ foreach ( XElement artifactElement in verticalManifest . Descendants ( elementName ) )
295299 {
296- string elementId = artifactElement . Attribute ( _idAttribute ) ? . Value
300+ string elementId = artifactElement . Attribute ( _idAttribute ) ? . Value
297301 ?? throw new ArgumentException ( $ "Required attribute '{ _idAttribute } ' not found in { elementName } element.") ;
298302
303+ // Filter out artifacts that are not "External" visibility.
304+ // Artifacts of "Vertical" visibility should have been filtered out in each individual vertical,
305+ // but artifacts of "Internal" visibility would have been included in each vertical's manifest (to enable feeding into join verticals).
306+ // We need to remove them here so they don't get included in the final merged manifest.
307+ // As we're in the final join, there should be no jobs after us. Therefore, we can also skip uploading them to the final artifacts folders
308+ // as no job should run after this job that would consume them.
309+ string ? visibility = artifactElement . Attribute ( _visibilityAttribute ) ? . Value ;
310+
311+ if ( visibility == _verticalVisibility )
312+ {
313+ Log . LogError ( $ "Artifact { elementId } has 'Vertical' visibility and should not be present in a vertical manifest.") ;
314+ continue ;
315+ }
316+ else if ( visibility == _internalVisibility )
317+ {
318+ Log . LogMessage ( MessageImportance . High , $ "Artifact { elementId } has 'Internal' visibility and will not be included in the final merged manifest.") ;
319+ continue ;
320+ }
321+ else if ( visibility is not ( null or "" or _externalVisibility ) )
322+ {
323+ Log . LogError ( $ "Artifact { elementId } has unknown visibility: '{ visibility } '") ;
324+ continue ;
325+ }
326+
299327 if ( addedArtifacts . TryAdd ( elementId , new AddedElement ( verticalName , artifactElement ) ) )
300328 {
301329 if ( elementName == _packageElementName )
@@ -327,7 +355,7 @@ private List<string> AddMissingElements(Dictionary<string, AddedElement> addedAr
327355
328356 private static string GetRequiredRootAttribute ( XDocument document , string attributeName )
329357 {
330- return document . Root ? . Attribute ( attributeName ) ? . Value
358+ return document . Root ? . Attribute ( attributeName ) ? . Value
331359 ?? throw new ArgumentException ( $ "Required attribute '{ attributeName } ' not found in root element.") ;
332360 }
333361
0 commit comments