-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
194 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 16 | ||
VisualStudioVersion = 16.0.30204.135 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevOpsArtifactDownloader", "DevOpsArtifactDownloader\DevOpsArtifactDownloader.csproj", "{79E8A515-9079-46BD-9034-E49E823E5F30}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{79E8A515-9079-46BD-9034-E49E823E5F30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{79E8A515-9079-46BD-9034-E49E823E5F30}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{79E8A515-9079-46BD-9034-E49E823E5F30}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{79E8A515-9079-46BD-9034-E49E823E5F30}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {C6561EFB-5086-4ECD-82AC-7786FEE7A208} | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>netcoreapp3.1</TargetFramework> | ||
<Authors>Alexander van der Kolk</Authors> | ||
<Company>Kolky.nl</Company> | ||
<Description>Tool to download the Latest Build Artifact from Azure DevOps.</Description> | ||
<Copyright>© 2020 Kolky.nl</Copyright> | ||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | ||
<PackageProjectUrl>https://github.com/Kolky/DevOpsArtifactDownloader</PackageProjectUrl> | ||
<RepositoryUrl>https://github.com/Kolky/DevOpsArtifactDownloader</RepositoryUrl> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="CommandLineParser" Version="2.8.0" /> | ||
<PackageReference Include="Microsoft.TeamFoundationServer.Client" Version="16.153.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<None Include="..\LICENSE"> | ||
<Pack>True</Pack> | ||
<PackagePath></PackagePath> | ||
</None> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
using System; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using CommandLine; | ||
using Microsoft.TeamFoundation.Build.WebApi; | ||
using Microsoft.VisualStudio.Services.Common; | ||
using Microsoft.VisualStudio.Services.WebApi; | ||
|
||
namespace DevOpsArtifactDownloader | ||
{ | ||
internal class Program | ||
{ | ||
private enum ExitCode : int | ||
{ | ||
Success = 0, | ||
NoBuildsAvailable = 1, | ||
SavingResultFailed = 2, | ||
} | ||
|
||
private class Options | ||
{ | ||
[Option('o', "organization", Required = true, HelpText = "Your Azure DevOps organization.")] | ||
public string Organization { get; set; } | ||
|
||
[Option('t', "pat", Required = true, HelpText = "Your Personal Access Token.")] | ||
public string PersonalAccessToken { get; set; } | ||
|
||
[Option('p', "project", Required = true, HelpText = "The specified project.")] | ||
public string Project { get; set; } | ||
|
||
[Option('d', "definition", Required = true, HelpText = "The pipeline definition-id, get it from the browser url.")] | ||
public int Defintion { get; set; } | ||
|
||
[Option('b', "branch", HelpText = "The specified branch, use git refs format. For example: /refs/heads/develop")] | ||
public string Branch { get; set; } | ||
|
||
[Option('a', "artifact", Required = true, HelpText = "The specified artifact name. Use {buildId}, {buildNumber} or {revision} to replace with associated details of the build.")] | ||
public string Artifact { get; set; } | ||
|
||
[Option('r', "result", Default = "Build.zip", HelpText = "The output file name, must end in '.zip'. Use {buildId}, {buildNumber} or {revision} to replace with associated details of the build.")] | ||
public string Result { get; set; } | ||
} | ||
|
||
private static async Task Main(string[] args) | ||
{ | ||
await Parser.Default.ParseArguments<Options>(args) | ||
.WithParsedAsync(Execute); | ||
} | ||
|
||
private static async Task Execute(Options options) | ||
{ | ||
// Create instance of VssConnection using Personal Access Token | ||
var connection = new VssConnection(new Uri($"https://dev.azure.com/{options.Organization}"), new VssBasicCredential(string.Empty, options.PersonalAccessToken)); | ||
var client = await connection.GetClientAsync<BuildHttpClient>(); | ||
|
||
// Find latest build for project, definition and branch. | ||
var builds = await client.GetBuildsAsync( | ||
options.Project, | ||
definitions: new[] { options.Defintion }, | ||
branchName: options.Branch, | ||
statusFilter: BuildStatus.Completed, | ||
resultFilter: BuildResult.Succeeded, | ||
queryOrder: BuildQueryOrder.FinishTimeDescending, | ||
top: 1); | ||
if (!builds.Any()) | ||
{ | ||
Environment.Exit((int)ExitCode.NoBuildsAvailable); | ||
return; | ||
} | ||
|
||
var build = builds.Single(); | ||
|
||
try | ||
{ | ||
using (var zip = await client.GetArtifactContentZipAsync(options.Project, build.Id, BuildArtifactName(options.Artifact, build))) | ||
using (var fileStream = File.OpenWrite(BuildResultFile(options.Result, build))) | ||
{ | ||
await zip.CopyToAsync(fileStream); | ||
} | ||
} | ||
catch (IOException) | ||
{ | ||
Environment.Exit((int)ExitCode.SavingResultFailed); | ||
} | ||
} | ||
|
||
private static string BuildArtifactName(string artifactName, Build build) | ||
{ | ||
return artifactName | ||
.Replace("{buildId}", build.Id.ToString()) | ||
.Replace("{buildNumer}", build.BuildNumber) | ||
.Replace("{revision}", build.BuildNumberRevision?.ToString() ?? string.Empty); | ||
} | ||
|
||
private static string BuildResultFile(string result, Build build) | ||
{ | ||
if (string.IsNullOrWhiteSpace(result)) | ||
{ | ||
return "Build.zip"; | ||
} | ||
|
||
if (!result.EndsWith(".zip")) | ||
{ | ||
return $"{BuildArtifactName(result, build)}.zip"; | ||
} | ||
|
||
return BuildArtifactName(result, build); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"profiles": { | ||
"DevOpsArtifactDownloader": { | ||
"commandName": "Project", | ||
"commandLineArgs": "-o *organization* -t *accesstoken* -p *project* -d 5 -b \"refs/heads/develop\" -a \"*project* #{buildId}\" -r Build.zip" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,24 @@ | ||
# DevOpsArtifactDownloader | ||
Tool to download the Latest Build Artifact from Azure DevOps | ||
Tool to download the Latest Build Artifact from Azure DevOps. | ||
|
||
## Why? | ||
With this tool you can use other tools developed in Azure DevOps on a private Jenkins behind a VPN connection. | ||
|
||
Use it to download your latest DevOps build artifacts through a Jenkins job. Which can be triggered on a successfull build by a webhook. The webhook can be sent to a public or private [smee.io](https://smee.io/) url which a local smee-client then passes to a jenkins server. Jenkins can trigger a job using the [Generic Webhook Trigger](https://plugins.jenkins.io/generic-webhook-trigger/) plugin. You could then make your downloaded DevOps build artifacts into local Jenkins artifacts, so other Jenkins jobs can use the latest DevOps artifacts. | ||
|
||
This keeps your development and building of tools fully in Azure DevOps. While being still able to use them in a private Jekins behind a VPN connection. | ||
|
||
Ofcourse it can also be deployed in other use-cases. | ||
|
||
## Usage | ||
Run via the commandline with arguments; | ||
|
||
-o, --organization Required. | ||
-t, --pat Required. | ||
-p, --project Required. | ||
-d, --definition Required. | ||
-b, --branch | ||
-a, --artifact Required. | ||
-r, --result (Default: Build.zip) | ||
--help Display this help screen. | ||
--version Display version information. |