Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Stage 1: https://hub.docker.com/_/microsoft-dotnet
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
ENV outputPath=/output/data/
WORKDIR /app
ENTRYPOINT ["dotnet", "ExportPipelineDefinitions.dll"]

# Disable .NET diagnostics so app does no need write permissions to /tmp
ENV COMPlus_EnableDiagnostics=0


# Stage 2: Build application with SDK
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /source

# copy csproj and restore as distinct layers
COPY *.sln .
COPY ExportPipelineDefinitions/*.csproj ./ExportPipelineDefinitions/
RUN dotnet restore

# copy everything else and build app
COPY ExportPipelineDefinitions/. ./ExportPipelineDefinitions/
WORKDIR /source/ExportPipelineDefinitions
RUN dotnet publish -o /app --no-restore


# Stage 3: Copy binaries to hardened runtime image
FROM base AS final
COPY --from=build /app ./
24 changes: 0 additions & 24 deletions ExportPipelineDefinitions/App.config

This file was deleted.

70 changes: 6 additions & 64 deletions ExportPipelineDefinitions/ExportPipelineDefinitions.csproj
Original file line number Diff line number Diff line change
@@ -1,70 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{AB417819-7751-4B6B-95C5-0A127625DC6E}</ProjectGuid>
<TargetFramework>net6.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>ExportPipelineDefinitions</RootNamespace>
<AssemblyName>ExportPipelineDefinitions</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Json, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c6752e45808247c2, processorArchitecture=MSIL">
<HintPath>..\packages\JSON.1.0.1\lib\net40\Json.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</None>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
100 changes: 80 additions & 20 deletions ExportPipelineDefinitions/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Runtime.InteropServices;

namespace ExportPipelineDefinitions
{
Expand Down Expand Up @@ -46,6 +47,7 @@ public class BuildDef
public int id;
public string name;
public string path;
public string type;
}

static List<BuildDef> definitionList = new List<BuildDef>();
Expand Down Expand Up @@ -122,18 +124,17 @@ static void Main(string[] args)
if (Directory.Exists(outputPath))
{
BuildCsvString(1, "Writing to column 1 flushes the csvColumns buffer to csvString");
File.WriteAllText(outputPath + @"\BuildDefinitions.csv", csvString);
File.WriteAllText(outputPath + Path.DirectorySeparatorChar + @"BuildDefinitions.csv", csvString);
}

Console.WriteLine("Done. Press any key");
Console.ReadKey();
Console.WriteLine("Done.");
}

public static void GetSettings()
{
personalAccessToken = Properties.Settings.Default.personalAccessToken;
organization = Properties.Settings.Default.organization;
outputPath = Properties.Settings.Default.outputPath;
personalAccessToken = Environment.GetEnvironmentVariable("personalAccessToken");
organization = Environment.GetEnvironmentVariable("organization");
outputPath = Environment.GetEnvironmentVariable("outputPath");

Validate(nameof(personalAccessToken), personalAccessToken);
Validate(nameof(organization), organization);
Expand All @@ -146,7 +147,7 @@ public static void Validate(string nameOfVar, string value)
{
throw new InvalidDataException(
string.Format(
"Invalid {0} value in file {1}.config.",
"Invalid {0} value in environment variable",
nameOfVar,
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName));
}
Expand Down Expand Up @@ -225,6 +226,7 @@ public static async Task PopulateBuildDefinitionList(string project = "SDK_v4")
bd.id = int.Parse(o["id"].ToString());
bd.name = o["name"].ToString();
bd.path = o["path"].ToString();
bd.type = o.SelectToken("repository.type").ToString();
definitionList.Add(bd);
}
}
Expand Down Expand Up @@ -313,23 +315,27 @@ public static async Task WriteDefinitionToFile(string project, string definition
// Write json to a file
string fileContent = json.ToString();

string directory = outputPath + project + "\\" + definitionType + "s\\" + buildDef.path;
string directory = outputPath + project + Path.DirectorySeparatorChar + definitionType + "s" + Path.DirectorySeparatorChar + buildDef.path;
directory = directory.Replace("/\\", "/");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
directory = directory.Replace("\\", "/");
}
System.IO.Directory.CreateDirectory(directory);
string buildName = buildDef.name.Replace("?", "").Replace(":", "");
if (isYamlPipeline)
{
directory += "\\" + buildName;
directory += Path.DirectorySeparatorChar + buildName;
System.IO.Directory.CreateDirectory(directory);
}
directory = directory.Replace("\\\\", "\\").Replace("\\\\", "\\");

string fullFilePath = directory + "\\" + buildDef.name.Replace("?", "").Replace(":", "") + ".json";
string fullFilePath = directory + Path.DirectorySeparatorChar + buildDef.name.Replace("?", "").Replace(":", "") + ".json";
System.IO.File.WriteAllText(fullFilePath, fileContent);
if (isYamlPipeline)
{
string saveDirectory = Directory.GetCurrentDirectory();
//Directory.SetCurrentDirectory(directory);
DownloadYamlFilesToDirectory(json, directory);
DownloadYamlFilesToDirectory(json, directory, project, buildDef.type);
//Directory.SetCurrentDirectory(saveDirectory);
}
}
Expand All @@ -355,7 +361,7 @@ public static bool CheckForYamlPipeline(JObject json)
return false;
}

public static void DownloadYamlFilesToDirectory(JObject json, string directory)
public static void DownloadYamlFilesToDirectory(JObject json, string directory, string project, string type)
{
// Download the .yml files from the GitHub repo.
// Get GitHub repo URL for this Azure project.
Expand Down Expand Up @@ -419,15 +425,69 @@ public static void DownloadYamlFilesToDirectory(JObject json, string directory)
logIndent = " "; // 8 spaces
}
string fileName = githubFileUrl.Substring(githubFileUrl.LastIndexOf('/') + 1);
string targetFullFilePath = $"{directory}\\{fileName}";
bool succeeded = DownloadFileFromGithub(githubFileUrl, targetFullFilePath, logIndent);
yamlFileNames.RemoveAt(0);
if (succeeded)
string targetFullFilePath = directory + Path.DirectorySeparatorChar + fileName;

if (type == "TfsGit")
{
string restUrl = "";
try {
restUrl = String.Format("https://{0}/{1}/{2}/_apis/pipelines/{3}/preview?api-version=7.1-preview.1", domain, organization, project, json["id"]);

using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "", personalAccessToken))));

var requestContent = new StringContent("{\"previewRun\":true}", Encoding.UTF8, "application/json");
var webRequest = new HttpRequestMessage(HttpMethod.Post, restUrl)
{
Content = requestContent
};
using (HttpResponseMessage response = client.Send(webRequest))
{
response.EnsureSuccessStatusCode();
using var reader = new StreamReader(response.Content.ReadAsStream());
string responseBody = reader.ReadToEnd();
if (responseBody.Contains("!DOCTYPE"))
{
throw new AccessViolationException(
string.Format(
"Cannot access Azure. Please ensure personalAccessToken and organization values are correct in file {0}.config.",
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName));
}
JObject jsonNew = JObject.Parse(responseBody);
using (StreamWriter outputFile = new StreamWriter(targetFullFilePath))
{
outputFile.Write(jsonNew["finalYaml"].ToString());
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.WriteLine(restUrl);
}

// There can be only one Azure DevOps YAML file per pipeline so we can break here.
break;
}
else
{
int count = yamlFileNames.Count;
yamlFileNames.AddRange(GetYamlTemplateReferencesFromFile(targetFullFilePath));
bool succeeded = DownloadFileFromGithub(githubFileUrl, targetFullFilePath, logIndent);
yamlFileNames.RemoveAt(0);
if (succeeded)
{
int count = yamlFileNames.Count;
yamlFileNames.AddRange(GetYamlTemplateReferencesFromFile(targetFullFilePath));
}
githubFileUrl = string.Empty;
}
githubFileUrl = string.Empty;
}
// Read .yml file from repo.
// Look for template references to other .yml files. Add any found to yamlFileNames list.
Expand Down
4 changes: 2 additions & 2 deletions ExportPipelineDefinitions/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyVersion("1.2.0.0")]
[assembly: AssemblyFileVersion("1.2.0.0")]
53 changes: 0 additions & 53 deletions ExportPipelineDefinitions/Properties/Settings.Designer.cs

This file was deleted.

17 changes: 0 additions & 17 deletions ExportPipelineDefinitions/Properties/Settings.settings

This file was deleted.

5 changes: 0 additions & 5 deletions ExportPipelineDefinitions/packages.config

This file was deleted.

Loading