Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev/initial #1

Merged
merged 22 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
fb73112
Add project files.
janstaelensskyline Dec 4, 2023
e48518b
Initial Upload code added.
janstaelensskyline Dec 5, 2023
a932b8e
Create main.yml
janstaelensskyline Dec 6, 2023
088d094
Code Cleanup.
janstaelensskyline Dec 7, 2023
c228e8c
Fixes basePath. Fixes casing issues in program arguments
janstaelensskyline Dec 8, 2023
16f754b
Fixed basepath.
janstaelensskyline Dec 8, 2023
d767e50
Code cleanup
janstaelensskyline Dec 8, 2023
09d1628
Adjusted EntryPoint for Library description.
janstaelensskyline Dec 8, 2023
229a3c8
Cleaned up unit tests.
janstaelensskyline Dec 8, 2023
3a49ced
Update CICD.Tools.CatalogUpload.Lib/CatalogArtifact.cs
janstaelensskyline Dec 12, 2023
50a582a
Update CICD.Tools.CatalogUpload.Lib/CatalogArtifact.cs
janstaelensskyline Dec 12, 2023
cdf7af7
Update CICD.Tools.CatalogUpload.Lib/CatalogArtifact.cs
janstaelensskyline Dec 12, 2023
df72ae7
Update CICD.Tools.CatalogUpload.Lib/CatalogArtifact.cs
janstaelensskyline Dec 12, 2023
d3f4f12
Update CICD.Tools.CatalogUpload/Program.cs
janstaelensskyline Dec 12, 2023
4b5c98f
Update CICD.Tools.CatalogUpload/Program.cs
janstaelensskyline Dec 12, 2023
e899b64
Update CICD.Tools.CatalogUpload/Program.cs
janstaelensskyline Dec 12, 2023
e227ca6
Update CICD.Tools.CatalogUpload/Program.cs
janstaelensskyline Dec 12, 2023
4897357
Applied review remarks
janstaelensskyline Dec 12, 2023
a2cb6c6
adjusted some comments
janstaelensskyline Dec 12, 2023
95d62f1
Fixed debug logging. Added debug log indicating its using the provide…
janstaelensskyline Dec 13, 2023
47c7974
Adjusted Environment Variables to
janstaelensskyline Dec 14, 2023
583cd52
Adjusted .net tools arguments to match Microsoft guidelines for comma…
janstaelensskyline Dec 15, 2023
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
34 changes: 34 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: DataMiner CICD NuGet Solution

# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events.
push:
branches: []
tags:
- "[0-9]+.[0-9]+.[0-9]+.[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+.[0-9]+-**"
- "[0-9]+.[0-9]+.[0-9]+-**"

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:

# Note: Tagging will push the nupackage to nuget.org using the provided NUGETAPIKEY. You can tag both a prerelease version (a.b.c-xxxx) or a stable release (a.b.c).
CICD:
uses: SkylineCommunications/_ReusableWorkflows/.github/workflows/NuGet Solution Master Workflow.yml@main
with:
referenceName: ${{ github.ref_name }}
runNumber: ${{ github.run_number }}
referenceType: ${{ github.ref_type }}
repository: ${{ github.repository }}
owner: ${{ github.repository_owner }}
sonarCloudProjectName: SkylineCommunications_Skyline.DataMiner.CICD.Tools.CatalogUpload
secrets:
sonarCloudToken: ${{ secrets.SONAR_TOKEN }}
pfx: ${{ secrets.PFX }}
pfxPassword: ${{ secrets.PFXPASSWORD }}
nugetApiKey: ${{ secrets.NUGETAPIKEY }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -360,4 +360,5 @@ MigrationBackup/
.ionide/

# Fody - auto-generated XML schema
FodyWeavers.xsd
FodyWeavers.xsd
/CICD.Tools.CatalogUpload/Properties/launchSettings.json
41 changes: 41 additions & 0 deletions CICD.Tools.CatalogUpload.Lib/CICD.Tools.CatalogUpload.Lib.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>disable</Nullable>
<AssemblyName>Skyline.DataMiner.CICD.Tools.CatalogUpload.Lib</AssemblyName>
<PackageVersion>1.0.1-alpaha1</PackageVersion>
<Version>1.0.1-alpaha1</Version>
<PackageTags>Skyline;DataMiner</PackageTags>
<PackageProjectUrl>https://skyline.be</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
<PackageIcon>Icon.png</PackageIcon>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Authors>SkylineCommunications</Authors>
<Company>Skyline Communications</Company>
<Description>
Library containing code to upload artifacts to the Skyline DataMiner Catalog (https://catalog.dataminer.services/).
Entry Point: new CatalogArtifact("pathToArtifact", "logger", "metaData").UploadAsync();
</Description>
<RootNamespace>Skyline.DataMiner.CICD.Tools.CatalogUpload.Lib</RootNamespace>
</PropertyGroup>

<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="" />
<None Include="LICENSE.txt" Pack="true" PackagePath="" />
<None Include="nuget\Icon.png" Pack="true" PackagePath="" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Skyline.DataMiner.CICD.FileSystem" Version="1.0.2-ReadAllBytes1" />
<PackageReference Include="Skyline.DataMiner.CICD.Tools.WinEncryptedKeys.Lib" Version="1.0.2" />
</ItemGroup>

</Project>
169 changes: 169 additions & 0 deletions CICD.Tools.CatalogUpload.Lib/CatalogArtifact.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
namespace Skyline.DataMiner.CICD.Tools.CatalogUpload.Lib
{
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

using Microsoft.Extensions.Logging;

using Newtonsoft.Json;

using Skyline.DataMiner.CICD.FileSystem;

/// <summary>
/// Allows Uploading an artifact to the Catalog using one of the below in order of priority:
/// <para>- provided key in upload argument (Unix/Windows)</para>
/// <para>- key stored as an Environment Variable called "DATAMINER_CATALOG_TOKEN". (Unix/Windows)</para>
/// <para>- key configured using Skyline.DataMiner.CICD.Tools.WinEncryptedKeys called "DATAMINER_CATALOG_TOKEN_ENCRYPTED" (Windows only)</para>
/// </summary>
public class CatalogArtifact
{
private readonly ILogger _logger;
private readonly CatalogMetaData metaData;

/// <summary>
/// Creates an instance of <see cref="CatalogArtifact"/>.
/// It searches for an optional dmCatalogToken in the "DATAMINER_CATALOG_TOKEN" or "DATAMINER_CATALOG_TOKEN_ENCRYPTED" Environment Variable.
/// </summary>
/// <param name="pathToArtifact">Path to the application package (.dmapp) or protocol package (.dmprotocol).</param>
/// <param name="service">An instance of <see cref="ICatalogService"/> used for communication.</param>
/// <param name="fileSystem">An instance of <see cref="IFileSystem"/> to access the filesystem. e.g. Skyline.DataMiner.CICD.FileSystem.Instance.</param>
/// <param name="logger">An instance of <see cref="ILogger"/> that will hold error, debug and other information.</param>
/// <param name="metaData">Contains package metadata.</param>
public CatalogArtifact(string pathToArtifact, ICatalogService service, IFileSystem fileSystem, ILogger logger, CatalogMetaData metaData)
{
this.metaData = metaData;
_logger = logger;
Fs = fileSystem;
cancellationTokenSource = new CancellationTokenSource();
catalogService = service;
PathToArtifact = pathToArtifact;
TryFindEnvironmentKey();
}

/// <summary>
/// Creates an instance of <see cref="CatalogArtifact"/> using a default HttpCatalogService with a new HttpClient for communication.
/// It searches for an optional dmCatalogToken in the "DATAMINER_CATALOG_TOKEN" or "DATAMINER_CATALOG_TOKEN_ENCRYPTED" Environment Variable for authentication.
/// </summary>
/// <remarks>WARNING: when wishing to upload several Artifacts it's recommended to use the CatalogArtifact(string pathToArtifact, ICatalogService service, IFileSystem fileSystem, ILogger logger).</remarks>
/// <param name="pathToArtifact">Path to the application package (.dmapp) or protocol package (.dmprotocol).</param>
/// <param name="logger">An instance of <see cref="ILogger"/> that will hold error, debug and other information.</param>
/// <param name="metaData">Contains package metadata.</param>
public CatalogArtifact(string pathToArtifact, ILogger logger, CatalogMetaData metaData) : this(pathToArtifact, CatalogServiceFactory.CreateWithHttp(new System.Net.Http.HttpClient(), logger), FileSystem.Instance, logger, metaData)
{
}

/// <summary>
/// Path to the application package (.dmapp) or protocol package (.dmprotocol).
/// </summary>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

///
/// Path to the application package (.dmapp) or protocol package (.dmprotocol).

public string PathToArtifact { get; private set; }

private CancellationTokenSource cancellationTokenSource { get; set; }

private ICatalogService catalogService { get; set; }

private IFileSystem Fs { get; set; }

private string keyFromEnv { get; set; }

/// <summary>
/// Cancels an ongoing upload. Create a new CatalogArtifact to attempt a new upload.
/// </summary>
public void CancelUpload()
{
_logger.LogDebug($"Upload cancellation requested for {PathToArtifact}");
cancellationTokenSource.Cancel();
}

/// <summary>
/// Uploads to the private catalog using the provided dmCatalogToken.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Uploads to the private catalog using the provided dmCatalogToken.
/// Uploads to the private catalog using the specified <paramref name="dmCatalogToken" />.

/// </summary>
/// <param name="dmCatalogToken">A provided token for the agent or organization as defined in https://admin.dataminer.services/.</param>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// <param name="dmCatalogToken">A provided token for the agent or organization as defined in https://admin.dataminer.services/.</param>
/// <param name="dmCatalogToken">A provided token for the Agent or organization as defined in https://admin.dataminer.services/.</param>

/// <returns>If the upload was successful or not.</returns>
public async Task<ArtifactUploadResult> UploadAsync(string dmCatalogToken)
{
if(dmCatalogToken != keyFromEnv)
{
_logger.LogDebug($"Attempting upload with provided argument as token for artifact: {PathToArtifact}...");
}

_logger.LogDebug($"Uploading {PathToArtifact}...");

byte[] packageData = Fs.File.ReadAllBytes(PathToArtifact);
var result = await catalogService.ArtifactUploadAsync(packageData, dmCatalogToken, metaData, cancellationTokenSource.Token).ConfigureAwait(false);
_logger.LogDebug($"Finished Uploading {PathToArtifact}");

_logger.LogInformation(JsonConvert.SerializeObject(result));
return result;
}

/// <summary>
/// Uploads to the private catalog using the DATAMINER_CATALOG_TOKEN or DATAMINER_CATALOG_TOKEN environment variable as the token.
/// </summary>
/// <returns>If the upload was successful or not.</returns>
/// <exception cref="InvalidOperationException">Uploading failed.</exception>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// <exception cref="InvalidOperationException">Uploading failed.</exception>
/// <exception cref="InvalidOperationException">Upload failed.</exception>

/// <exception cref="UnauthorizedAccessException">Uploading failed due to invalid Token.</exception>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// <exception cref="UnauthorizedAccessException">Uploading failed due to invalid Token.</exception>
/// <exception cref="UnauthorizedAccessException">Upload failed due to invalid Token.</exception>

public async Task<ArtifactUploadResult> UploadAsync()
{
if (String.IsNullOrWhiteSpace(keyFromEnv))
{
throw new InvalidOperationException("Uploading failed, missing token in environment variable DATAMINER_CATALOG_TOKEN or DATAMINER_CATALOG_TOKEN_ENCRYPTED.");
}

_logger.LogDebug($"Attempting upload with Environment Variable as token for artifact: {PathToArtifact}...");
return await UploadAsync(keyFromEnv).ConfigureAwait(false);
}

/// <summary>
/// Attempts to find the necessary API key in Environment Variables. In order of priority:
/// <para>- key stored as an Environment Variable called "DATAMINER_CATALOG_TOKEN". (unix/win)</para>
/// <para>- key configured using Skyline.DataMiner.CICD.Tools.WinEncryptedKeys called "DATAMINER_CATALOG_TOKEN_ENCRYPTED" (windows only)</para>
/// </summary>
private void TryFindEnvironmentKey()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
try
{
var encryptedKey = WinEncryptedKeys.Lib.Keys.RetrieveKey("DATAMINER_CATALOG_TOKEN_ENCRYPTED");
if (encryptedKey != null)
{
string keyFromWinEncryptedKeys = new System.Net.NetworkCredential(string.Empty, encryptedKey).Password;

if (!String.IsNullOrWhiteSpace(keyFromWinEncryptedKeys))
{
_logger.LogDebug("OK: Found token in Env Variable: 'DATAMINER_CATALOG_TOKEN_ENCRYPTED' created by WinEncryptedKeys.");
keyFromEnv = keyFromWinEncryptedKeys;
}
}
}
catch (InvalidOperationException)
{
// Gobble up, no key means we try the next thing.
}
}

//var config = new ConfigurationBuilder()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove commented out code

// .AddUserSecrets<CatalogArtifact>()
// .Build();
//string keyFromEnvironment = config["DATAMINER_CATALOG_TOKEN"];

string keyFromEnvironment = Environment.GetEnvironmentVariable("DATAMINER_CATALOG_TOKEN");

if (!String.IsNullOrWhiteSpace(keyFromEnvironment))
{
if (!String.IsNullOrWhiteSpace(keyFromEnv))
{
_logger.LogDebug("OK: Overriding 'DATAMINER_CATALOG_TOKEN_ENCRYPTED' with found token in Env Variable: 'DATAMINER_CATALOG_TOKEN'.");
}
else
{
_logger.LogDebug("OK: Found token in Env Variable: 'DATAMINER_CATALOG_TOKEN'.");
}

keyFromEnv = keyFromEnvironment;
}
}
}
}
Loading