Skip to content

Commit 5be8bae

Browse files
committed
Changed building before publishing to be opt-in.
1 parent 0a4dfb9 commit 5be8bae

File tree

3 files changed

+137
-20
lines changed

3 files changed

+137
-20
lines changed

src/toolkit/nuget/build/imports/PublishToMarketplace.targets

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
<Project>
22

3+
<!--
4+
Provide a way for a build to be done prior to publishing, so
5+
that building and publishing can be done in a single step.
6+
-->
7+
<PropertyGroup Condition="'$(BuildBeforePublish)' == 'true'">
8+
<PublishToMarketplaceDependsOn>Rebuild</PublishToMarketplaceDependsOn>
9+
</PropertyGroup>
10+
311
<ItemGroup>
412
<!--
513
Update the build tools NuGet package reference to generate a path property. This will
@@ -11,7 +19,7 @@
1119
</PackageReference>
1220
</ItemGroup>
1321

14-
<Target Name="PublishToMarketplace" DependsOnTargets="Rebuild">
22+
<Target Name="PublishToMarketplace" DependsOnTargets="$(PublishToMarketplaceDependsOn)">
1523
<Message Text="Publishing extension to the marketplace..." Importance="normal"/>
1624

1725
<!-- Before anything else happens, ensure that only "Release" builds can be published. -->
@@ -58,12 +66,18 @@
5866
Text="A personal access token must be specified in the 'PersonalAccessToken' build property."
5967
/>
6068

69+
<!-- Verify that the extension file was found. -->
70+
<Error
71+
Condition="'$(PublishExtension)' == '' or !Exists('$(PublishExtension)')"
72+
Text="The extension file could not be found at '$(PublishExtension)'."
73+
/>
74+
6175
<!-- Everything should be valid now, so define the command to publish the extension. -->
6276
<PropertyGroup>
6377
<PublishCommand>&quot;$(VsixPublisher)&quot; publish -personalAccessToken &quot;$(PersonalAccessToken)&quot; -payload &quot;$(PublishExtension)&quot; -publishManifest &quot;$(PublishManifest)&quot;</PublishCommand>
6478
<PublishCommand Condition="'$(PublishIgnoreWarnings)' != ''">$(PublishCommand) -ignoreWarnings &quot;$(PublishIgnoreWarnings)&quot;</PublishCommand>
6579
</PropertyGroup>
66-
80+
6781
<Exec
6882
Command="$(PublishCommand)"
6983
StandardOutputImportance="normal"

test/toolkit/Community.VisualStudio.Toolkit.UnitTests/MSBuild/ProjectFixture.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ internal class TestProject
1717

1818
private readonly string _directory;
1919
private readonly List<string> _files = new();
20-
private readonly List<string> _props = new();
21-
private readonly List<string> _targets = new();
20+
private readonly List<string> _propsImports = new();
21+
private readonly List<string> _targetsImports = new();
22+
private readonly List<string> _targetsElements = new();
2223

2324
public TestProject(string directory)
2425
{
@@ -28,7 +29,7 @@ public TestProject(string directory)
2829
public void ImportTargets(string fileName)
2930
{
3031
string path = GetTargetsPath(fileName);
31-
_targets.Add($"<Import Project='{path}' />");
32+
_targetsImports.Add($"<Import Project='{path}' />");
3233
}
3334

3435
private static string GetTargetsPath(string fileName, [CallerFilePath] string thisFilePath = "")
@@ -50,6 +51,11 @@ public void AddFile(string fileName, string contents)
5051
_files.Add($"<Compile Include='{fileName}'/>");
5152
}
5253

54+
public void AddTargetElement(string element)
55+
{
56+
_targetsElements.Add(element);
57+
}
58+
5359
public async Task<CompilationResult> CompileAsync(CompileOptions options, ITestOutputHelper outputHelper)
5460
{
5561
WriteFiles();
@@ -135,7 +141,7 @@ private void WriteProject()
135141
<VSToolsPath Condition=""'$(VSToolsPath)' == ''"">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
136142
</PropertyGroup>
137143
<Import Project='$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props' Condition=""Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"" />
138-
{string.Join(Environment.NewLine, _props)}
144+
{string.Join(Environment.NewLine, _propsImports)}
139145
<PropertyGroup>
140146
<Configuration Condition="" '$(Configuration)' == '' "">Debug</Configuration>
141147
<Platform Condition="" '$(Platform)' == '' "">AnyCPU</Platform>
@@ -161,7 +167,8 @@ private void WriteProject()
161167
<PrivateAssets>all</PrivateAssets>
162168
</PackageReference>
163169
</ItemGroup>
164-
{string.Join(Environment.NewLine, _targets)}
170+
{string.Join(Environment.NewLine, _targetsElements)}
171+
{string.Join(Environment.NewLine, _targetsImports)}
165172
<Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
166173
<Import Project='$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets' Condition=""'$(VSToolsPath)' != ''"" />
167174
</Project>");

test/toolkit/Community.VisualStudio.Toolkit.UnitTests/MSBuild/PublishToMarketplaceTests.cs

Lines changed: 109 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public async Task FailsWhenConfigurationIsDebugAsync()
2929
TestProject project = CreateProject("Extension");
3030
WritePublishManifest("Extension/publish.json");
3131

32-
CompilationResult result = await BuildAsync(project, new CompileOptions
32+
CompilationResult result = await BuildAndPublishAsync(project, new CompileOptions
3333
{
3434
Properties = new Properties
3535
{
@@ -46,7 +46,7 @@ public async Task FailsWhenPublishManifestIsNotFoundAsync()
4646
{
4747
TestProject project = CreateProject("Extension");
4848

49-
CompilationResult result = await BuildAsync(project, new CompileOptions
49+
CompilationResult result = await BuildAndPublishAsync(project, new CompileOptions
5050
{
5151
Properties = new Properties
5252
{
@@ -63,7 +63,7 @@ public async Task FailsWhenSpecifiedPublishManifestDoesNotExistAsync()
6363
{
6464
TestProject project = CreateProject("Extension");
6565

66-
CompilationResult result = await BuildAsync(project, new CompileOptions
66+
CompilationResult result = await BuildAndPublishAsync(project, new CompileOptions
6767
{
6868
Properties = new Properties
6969
{
@@ -82,7 +82,7 @@ public async Task FailsWhenPersonalAccessTokenIsNotSpecifiedAsync()
8282
TestProject project = CreateProject("Extension");
8383
WritePublishManifest("Extension/publish.json");
8484

85-
CompilationResult result = await BuildAsync(project, new CompileOptions
85+
CompilationResult result = await BuildAndPublishAsync(project, new CompileOptions
8686
{
8787
Properties = new Properties
8888
{
@@ -99,7 +99,7 @@ public async Task CallsVsixPublisherWithTheCorrectArgumentsAsync()
9999
TestProject project = CreateProject("Extension");
100100
WritePublishManifest("Extension/publish.json");
101101

102-
CompilationResult result = await BuildAsync(project, new CompileOptions
102+
CompilationResult result = await BuildAndPublishAsync(project, new CompileOptions
103103
{
104104
Properties = new Properties
105105
{
@@ -129,7 +129,7 @@ public async Task CanFindThePublishManifestFileAboveTheProjectDirectoryAsync()
129129
TestProject project = CreateProject("source/Extension");
130130
WritePublishManifest("publish.json");
131131

132-
CompilationResult result = await BuildAsync(project, new CompileOptions
132+
CompilationResult result = await BuildAndPublishAsync(project, new CompileOptions
133133
{
134134
Properties = new Properties
135135
{
@@ -159,7 +159,7 @@ public async Task UsesTheSpecifiedPublishManifestFileAsync()
159159
TestProject project = CreateProject("Extension");
160160
WritePublishManifest("bar.json");
161161

162-
CompilationResult result = await BuildAsync(project, new CompileOptions
162+
CompilationResult result = await BuildAndPublishAsync(project, new CompileOptions
163163
{
164164
Properties = new Properties
165165
{
@@ -190,7 +190,7 @@ public async Task CanIgnoreWarningsInVsixPublisherAsync()
190190
TestProject project = CreateProject("Extension");
191191
WritePublishManifest("Extension/publish.json");
192192

193-
CompilationResult result = await BuildAsync(project, new CompileOptions
193+
CompilationResult result = await BuildAndPublishAsync(project, new CompileOptions
194194
{
195195
Properties = new Properties
196196
{
@@ -222,7 +222,7 @@ public async Task FailsWhenVsixPublisherWritesToStandardErrorAsync()
222222
TestProject project = CreateProject("Extension");
223223
WritePublishManifest("Extension/publish.json");
224224

225-
CompilationResult result = await BuildAsync(project, new CompileOptions
225+
CompilationResult result = await BuildAndPublishAsync(project, new CompileOptions
226226
{
227227
Properties = new Properties
228228
{
@@ -244,7 +244,7 @@ public async Task FailsWhenVsixPublisherExitsWithNonZeroValueAsync()
244244
TestProject project = CreateProject("Extension");
245245
WritePublishManifest("Extension/publish.json");
246246

247-
CompilationResult result = await BuildAsync(project, new CompileOptions
247+
CompilationResult result = await BuildAndPublishAsync(project, new CompileOptions
248248
{
249249
Properties = new Properties
250250
{
@@ -275,7 +275,8 @@ public async Task CanFindTheRealVsixPublisherExecutableAsync()
275275
Properties = new Properties
276276
{
277277
Configuration = "Release",
278-
PersonalAccessToken = "foo"
278+
PersonalAccessToken = "foo",
279+
BuildBeforePublish = "true"
279280
}
280281
}, _outputHelper);
281282

@@ -293,7 +294,7 @@ public async Task CanOverrideTheExtensionFilePathAsync()
293294
Directory.CreateDirectory(Path.GetDirectoryName(extensionFileName));
294295
File.WriteAllText(extensionFileName, "");
295296

296-
CompilationResult result = await BuildAsync(project, new CompileOptions
297+
CompilationResult result = await BuildAndPublishAsync(project, new CompileOptions
297298
{
298299
Target = "PublishToMarketplace",
299300
Properties = new Properties
@@ -319,6 +320,86 @@ public async Task CanOverrideTheExtensionFilePathAsync()
319320
);
320321
}
321322

323+
[Fact]
324+
public async Task FailsIfExtensionFileDoesNotExistAsync()
325+
{
326+
TestProject project = CreateProject("Extension");
327+
WritePublishManifest("Extension/publish.json");
328+
329+
string extensionFileName = Path.Combine(_directory.FullPath, "output", "file.vsix");
330+
CompilationResult result = await PublishAsync(project, new CompileOptions
331+
{
332+
Target = "PublishToMarketplace",
333+
Properties = new Properties
334+
{
335+
Configuration = "Release",
336+
PersonalAccessToken = "foo",
337+
PublishExtension = extensionFileName
338+
}
339+
});
340+
341+
AssertError(result, $"The extension file could not be found at '{extensionFileName}'");
342+
}
343+
344+
[Fact]
345+
public async Task DoesNotBuildBeforePublishingByDefaultAsync()
346+
{
347+
TestProject project = CreateProject("Extension");
348+
WritePublishManifest("Extension/publish.json");
349+
350+
// Write an extension file because it won't be built for us.
351+
string extensionFileName = Path.Combine(_directory.FullPath, "file.vsix");
352+
Directory.CreateDirectory(Path.GetDirectoryName(extensionFileName));
353+
File.WriteAllText(extensionFileName, "");
354+
355+
project.AddTargetElement(@"
356+
<Target Name='LogBuild' BeforeTargets='Build'>
357+
<Message Text='Build target is running.' Importance='high' />
358+
</Target>
359+
");
360+
361+
CompilationResult result = await PublishAsync(project, new CompileOptions
362+
{
363+
Target = "PublishToMarketplace",
364+
Properties = new Properties
365+
{
366+
Configuration = "Release",
367+
PersonalAccessToken = "foo",
368+
PublishExtension = extensionFileName
369+
},
370+
});
371+
372+
Assert.Equal(0, result.ExitCode);
373+
Assert.DoesNotContain("Build target is running.", result.StandardOutput.Select((x) => x.Trim()));
374+
}
375+
376+
[Fact]
377+
public async Task BuildsBeforePublishingWhenOptionIsEnabledAsync()
378+
{
379+
TestProject project = CreateProject("Extension");
380+
WritePublishManifest("Extension/publish.json");
381+
382+
project.AddTargetElement(@"
383+
<Target Name='LogBuild' BeforeTargets='Build'>
384+
<Message Text='Build target is running.' Importance='high' />
385+
</Target>
386+
");
387+
388+
CompilationResult result = await PublishAsync(project, new CompileOptions
389+
{
390+
Target = "PublishToMarketplace",
391+
Properties = new Properties
392+
{
393+
Configuration = "Release",
394+
PersonalAccessToken = "foo",
395+
BuildBeforePublish = "true"
396+
},
397+
});
398+
399+
Assert.Equal(0, result.ExitCode);
400+
Assert.Contains("Build target is running.", result.StandardOutput.Select((x) => x.Trim()));
401+
}
402+
322403
private TestProject CreateProject(string subDirectory)
323404
{
324405
TestProject project = new(Path.Combine(_directory.FullPath, subDirectory));
@@ -334,7 +415,15 @@ private void WritePublishManifest(string fileName)
334415
File.WriteAllText(Path.Combine(_directory.FullPath, fileName), "");
335416
}
336417

337-
private async Task<CompilationResult> BuildAsync(TestProject project, CompileOptions options)
418+
private async Task<CompilationResult> BuildAndPublishAsync(TestProject project, CompileOptions options)
419+
{
420+
CompilationResult buildResult = await BuildAsync(project, options);
421+
Assert.Equal(0, buildResult.ExitCode);
422+
423+
return await PublishAsync(project, options);
424+
}
425+
426+
private async Task<CompilationResult> PublishAsync(TestProject project, CompileOptions options)
338427
{
339428
options.Target = "PublishToMarketplace";
340429

@@ -344,6 +433,12 @@ private async Task<CompilationResult> BuildAsync(TestProject project, CompileOpt
344433
return await project.CompileAsync(options, _outputHelper);
345434
}
346435

436+
private async Task<CompilationResult> BuildAsync(TestProject project, CompileOptions options)
437+
{
438+
options.Target = "Build";
439+
return await project.CompileAsync(options, _outputHelper);
440+
}
441+
347442
private static async Task DrainReaderAsync(StreamReader reader, Action<string> output)
348443
{
349444
string line;
@@ -433,6 +528,7 @@ private class Properties
433528
public string? PersonalAccessToken { get; set; }
434529
public string? PublishIgnoreWarnings { get; set; }
435530
public string? PublishExtension { get; set; }
531+
public string? BuildBeforePublish { get; set; }
436532
}
437533
}
438534
}

0 commit comments

Comments
 (0)