Lib/get_artifact.psm1

<#
    .SYNOPSIS
        Get NAF Artifacts
 
    .DESCRIPTION
        Get NAF Artifacts
 
    .NOTES
        Author : hillesheim@n-dimensions.de
        Version : 1.0
        DateLastChanged : 2023-11-28
#>
 

Using Module .\helper.psm1

Param ( 
    [Switch] $Auto 
)

Write-Host "Load nested module 'get_artifact' ... "; 

# ************************************************************************************************
# ************************************************************************************************
#region DECLARATION
    
    # ************************************************************************************************
    #region TYPES

    #endregion

    # ************************************************************************************************
    #region VARIABLES_USER
        
    #endregion

    # ************************************************************************************************
    #region VARIABLES_SYSTEM

    [String] $jobMsg = "Get NAF Artifacts"; 
    [String] $psScriptFilePath = $MyInvocation.MyCommand.Definition; 
    [String] $psScriptFolderPath = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent; 

    [String] $defaultUrlArtifactsCredproviderPsScript = "https://aka.ms/install-artifacts-credprovider.ps1"; 

    #endregion

#endregion

# ************************************************************************************************
# ************************************************************************************************
#region FUNCTIONS_PUBLIC

# ************************************************************************************************
# Get artifact

Function Get-Artifact {

    # Select jobstep
    $enumJobSteps_GetArtifact = "JobSteps_GetArtifact" -as [System.Type]; 
    [JobSteps_GetArtifact[]] $selection = `
        Show-EnumSelection `
                -Enum $enumJobSteps_GetArtifact `
                -Default $defaultJobSteps_GetArtifact `
                -Title "Job Steps: Please Select"
    Write-Host ("Selected job steps: "); 
    $selection `
        | ForEach-Object {
            Write-Host ("- {0}" -f $_); 
        }   

    # Open script editor
    If ($selection -contains [JobSteps_GetArtifact]::OpenScriptEditor) {
        Open-ScriptEditor `
            -Filepath $psScriptFilePath 
    }
   
    # Select artifact & download
    If ($selection -contains [JobSteps_GetArtifact]::DownloadArtifact) {

        Initialize-Artifact `
            -NugetPackages $Global:nugetPackages `
            -NugetSettings $Global:nugetSettings `
            -ArtifactSettings $Global:artifactSettings; 
        
        # Select artifact
        [NugetPackage[]] $selectedPackages = `
            Select-Artifact `
                -NugetPackages $NugetPackages; 
        
        # Download
        $selectedPackages `
            | ForEach-Object {
                Invoke-Download `
                    -NugetPackage $_ `
                    -NugetSettings $Global:nugetSettings `
                    -ArtifactSettings $Global:artifactSettings; 
            }
        
    }
            
    # Abort
    If($selection -contains [JobSteps_GetArtifact]::Abort) {
        Return; 
    }
    
        # Run another job
        $userInput = Read-Host("Run another job (y|n)? Press ENTER for 'y'"); 
        If("" -eq $userInput ){
            Get-Artifact; 
        }
    

}

#endregion

# ************************************************************************************************
# ************************************************************************************************
#region FUNCTIONS_PRIVATE

# ************************************************************************************************
# Get path from pattern
Function Get-PathFromPattern {
    Param(
        [FileOrFolderPatternType] $FileOrFolderPatternType, 
        [NugetPackage] $NugetPackage, 
        [NugetSettings] $NugetSettings, 
        [String] $Folder 
    )

    [String] $rtrVal = $null; 
    [String] $path = $null; 

    # File or folder patterns
    [HashTable] $patterns = [ordered]@{
        NupkgFile = "<PROGRAM_FOLDER>\Packages\<PACKAGE_ID>\<PACKAGE_ID>.<VERSION>.nupkg";
        NupkgFolder = "<PROGRAM_FOLDER>\Packages\<PACKAGE_ID>"; 
        NugetConfigFile = "<PROGRAM_FOLDER>\nuget.config"; 
    }

    $testRequirements = {
        Param(
            [String] $RequiredParamenters
        )

        [String[]] $pRequired = $RequiredParamenters.Split(","); 

        [HashTable] $params = @{
            NugetPackage  = -Not($null -eq $NugetPackage); 
            NugetSettings = -Not($null -eq $NugetSettings); 
            Folder        = -Not($null -eq $Folder); 
        }

        ForEach ( $rp in $pRequired ) {
            If(-Not($params[$rp])){
                Write-Host ("Test requirements failed: the required parameter '{0}' is null. Abort" -f $rp) -ForegroundColor Red; 
                Return; 
            }
        }
    
    }

    Write-Host ("Get file path using pattern ... "); 

    # Type "NupkgFile"
    If($FileOrFolderPatternType -eq ([FileOrFolderPatternType]::NupkgFile)){
        
        # Test requirements
        Invoke-Command `
            $testRequirements `
            -ArgumentList ("NugetPackage,NugetSettings");
        
        # NupkgFile = "<PROGRAM_FOLDER>\Packages\<PACKAGE_ID>\<PACKAGE_ID>.<VERSION>.nupkg";
        $path = $patterns["NupkgFile"].Replace("<PROGRAM_FOLDER>", $NugetSettings.NugetProgramFolder); 
        $path = $path.Replace("<PACKAGE_ID>", $NugetPackage.Id); 
        $path = $path.Replace("<VERSION>", $NugetPackage.Version); 
    }

    # Type "NupkgFolder"
    If($FileOrFolderPatternType -eq [FileOrFolderPatternType]::NupkgFolder) { 
         
        # Test requirements
        Invoke-Command `
            $testRequirements `
            -ArgumentList "NugetPackage,NugetSettings";

        $path = $patterns["NupkgFolder"].Replace("<PROGRAM_FOLDER>", $NugetSettings.NugetProgramFolder); 
        $path = $path.Replace("<PACKAGE_ID>", $NugetPackage.Id); 
    }

    # Type "NugetConfigFile"
    If($FileOrFolderPatternType -eq ([FileOrFolderPatternType]::NugetConfigFile)){

        # Test requirements
        Invoke-Command `
            $testRequirements `
            -ArgumentList ("NugetSettings");

        $path = $patterns["NugetConfigFile"].Replace("<PROGRAM_FOLDER>", $NugetSettings.NugetProgramFolder); 
    }
    

    # Return
    $rtrVal = $path; 
    Write-Output $rtrVal; 

}

# ************************************************************************************************
# Select artifact

Function Select-Artifact {
    Param(
        [NugetPackage[]] $NugetPackages 
    )

    [NugetPackage[]] $rtrVal = @(); 
    [NugetPackage[]] $packages = @(); 

    [String[]] $artifactNames = @(); 
    $NugetPackages `
        | ForEach-Object {
            $artifactNames += $_.Name; 
        }

    [String[]] $selectedArtifacts = `
        Show-ListSelection `
            -List $artifactNames `
            -Default @(1) `
            -Title "PLEASE SELECT ARTIFACT"; 

    $NugetPackages `
        | ForEach-Object {
            If( $selectedArtifacts -contains $_.Name){
                $packages += $_; 
            }
        }

    # Return
    $rtrVal = $packages; 
    Write-Output $rtrVal; 
}

# ************************************************************************************************
# Initialize artifact

Function Initialize-Artifact {
    Param(
        [NugetPackage[]] $NugetPackages, 
        [NugetSettings] $NugetSettings, 
        [ArtifactSettings] $ArtifactSettings 
    )

    Write-Host ( "Initialize artifact ... " );    

    # Test nuget program installation
    If(-Not(Test-Path -Path $NugetSettings.NugetProgramFolder )){
        Install-NugetCli;  
    }

    # Reset program/packages folders
    Write-Host ("- Reset program/packages folders ... "); 
    $NugetPackages `
        | ForEach-Object { 
            [String] $packageFolder = "<PROGRAM_FOLDER>\Packages\<PACKAGE_BASENAME>"; 
            $packageFolder = $packageFolder.Replace("<PROGRAM_FOLDER>", $NugetSettings.NugetProgramFolder); 
            $packageFolder = $packageFolder.Replace("<PACKAGE_BASENAME>", $_.BaseName); 
            
            # Reset
            If(Test-Path -Path $packageFolder){ 
                Remove-Item `
                    -Path $packageFolder `
                    -Recurse `
                    -Force; 
            }
            New-Item -Path $packageFolder -ItemType Directory;             
        }
    
    # Test artifact download folders
    Write-Host ("- Test artifact download folders ... "); 
    $NugetPackages `
        | ForEach-Object {
            [String] $folder = $_.DownloadFolder; 
            If(-Not (Test-Path $folder)) {
                Write-Host ( " Create folder '{0}' ... " -f $folder ); 
                New-Item -Path $folder -ItemType Directory; 
            } 
        }
   
    # Install Azure Artifacts Credential Provider
    Write-Host "- Install Azure Artifacts Credential Provider"; 
    Invoke-Expression "& { $(irm $ArtifactSettings.CredProviderInstallUrl) }"

}

# ************************************************************************************************
# Invoke download

Function Invoke-Download {
    Param (
        [NugetPackage] $NugetPackage, 
        [NugetSettings] $NugetSettings, 
        [ArtifactSettings] $ArtifactSettings 
    )

    [String] $outputDirectory = $null; 

    Write-Host ( "Invoke artifact download for '{0}' ... " -f $NugetPackage.Name ); 

    $outputDirectory = [System.IO.Path]::Combine($NugetSettings.NugetProgramFolder, "Packages", $NugetPackage.BaseName); 

    # Clean package program folder
# Write-Host ("Clean package install/output folder '{0}' ... " -f $NugetSettings.NugetPackagesInstallFolder);
#
# Remove-Item `
# -Path $NugetSettings.NugetPackagesInstallFolder `
# -Recurse `
# -Force;

    # Clear nuget cache
    Set-Location $NugetSettings.NugetProgramFolder; 
    Write-Host "Clear nuget cache ... "; 
    .\nuget.exe `
        locals `
        all `
        -clear
    
    # Download to program folder
    # "https://pkgs.dev.azure.com/n-dimensions-dev/NAF/_packaging/NdimensionsAutomationModules/nuget/v3/index.json"
    Write-Host ( "Download nuget package '{0}' from Azure Artifact to program folder '{1}' ... " -f $NugetPackage.Name, $outputDirectory ) -ForegroundColor Yellow; 
    .\nuget.exe `
        install $NugetPackage.BaseName `
        -Source $NugetPackage.ArtifactFeedUrl `
        -OutputDirectory $outputDirectory `
        -DependencyVersion Ignore; 

    # Copy to local destination folder
    Copy-Artifact `
        -NugetPackage $NugetPackage `
        -NugetSettings $NugetSettings; 
}

# ************************************************************************************************
# Copy artifact from program folder to final destination
Function Copy-Artifact {
    Param(
        [NugetPackage] $NugetPackage, 
        [NugetSettings] $NugetSettings
    )

    Write-Host ("Copy package '{0}' from program folder to local target folder '{1}' ... " -f $NugetPackage.Name, $NugetPackage.DownloadFolder) -ForegroundColor Yellow; 

    # nupkg with latest version
    [String] $packageBaseFolder = "<PROGRAM_FOLDER>\Packages\<PACKAGE_BASENAME>"; 
    $packageBaseFolder = $packageBaseFolder.Replace("<PROGRAM_FOLDER>", $NugetSettings.NugetProgramFolder); 
    $packageBaseFolder = $packageBaseFolder.Replace("<PACKAGE_BASENAME>", $NugetPackage.BaseName); 
    $packageFolder = `
        (Get-ChildItem `
            -Path $packageBaseFolder `
            -Directory `
            | Sort-Object `
                -Property BaseName `
                -Descending `
            | Select-Object `
                -First 1).BaseName; 
    
        If($null -eq $packageFolder) {
           Write-Host ("Program package folder is empty. Abort") -ForegroundColor Red; 
        Return; 
    }

    [String] $sourceFolder = "<PROGRAM_FOLDER>\Packages\<PACKAGE_BASENAME>\<PACKAGE_BASENAME_VERSION>\content"; 
    $sourceFolder = $sourceFolder.Replace("<PROGRAM_FOLDER>", $NugetSettings.NugetProgramFolder); 
    $sourceFolder = $sourceFolder.Replace("<PACKAGE_BASENAME>", $NugetPackage.BaseName); 
    $sourceFolder = $sourceFolder.Replace("<PACKAGE_BASENAME_VERSION>", $packageFolder); 

    Write-Host ("Source folder = '{0}'" -f $sourceFolder); 

    # Target folder
    $targetFolder = $NugetPackage.DownloadFolder; 

    # Clean up target folder
# Remove-Item `
# -Path $targetFolder `
# -Recurse `
# -Force;

    # Copy files
    Get-ChildItem `
        -Path $sourceFolder `
        -File `
        | ForEach-Object { 
            Copy-Item `
                -Path $_ `
                -Destination $targetFolder `
                -Force; 
        }

    # Copy folders
    Get-ChildItem `
        -Path "$sourceFolder" `
        -Directory `
        | ForEach-Object { 
            Copy-Item `
                -Path "$_" `
                -Destination "$targetFolder" `
                -Recurse `
                -Force; 
        }
}

#endregion

# ************************************************************************************************
# ************************************************************************************************
#region QUEUED

# # ************************************************************************************************
# # Set artifact api key
#
# Function Set-ArtifactFeedApiKey {
# Param (
# [NugetSettings] $NugetSettings,
# [ArtifactSettings] $ArtifactSettings
# )
#
# Write-Host ( "Add nuget api key ... " ); #-f $ArtifactSettings.ApiKey, $NugetSettings.NuGetSourceName );
#
# cd $NugetSettings.NugetProgramFolder;
#
# # Action
# Write-Host ( "- Nuget api key properties: " );
# Write-Host ( " Api key: '{0}'" -f $ArtifactSettings.AzApiKey );
# Write-Host ( " Source: '{0}'" -f $NugetSettings.NuGetSourceName );
#
# .\nuget.exe `
# setapikey $ArtifactSettings.AzApiKey `
# -source $ArtifactSettings.AzArtifactFeedUrl;
# }
#
# # ************************************************************************************************
# # Install nuget packages
#
## ************************************************************************************************
## Copy artifacts
#
#Function Copy-Artifacts {
# Param (
# [NugetSettings] $NugetSettings,
# [ArtifactSettings] $ArtifactSettings
# )
#
# Write-Host ( "Copy artifacts" );
#
# # Process package folders
# Foreach ( $p in $NugetSettings.NugetPackages ) {
#
# Write-Log (" - '{0}' ... " -f $p.Description) -LogFile $Logfile -CopyToConsole $true;
#
# # Get folder for latest nuget package version
# [String] $packageFolder = `
# Get-ChildItem -Path $NugetSettings.NugetPackagesInstallFolder -Directory `
# | Where-Object { $_.BaseName -like ($p.Name + "*") } `
# | Sort-Object { $_.Name } `
# | Select-Object -Last 1;
#
# # Extract version
# [System.Io.DirectoryInfo] $dirInfo = [System.Io.DirectoryInfo]::new($packageFolder);
# [Version] $nugetPackageVersion = $dirInfo.Name.Substring( $p.Name.Length + 1 );
# Write-Host ( "- Nuget package version: '{0}'" -f $nugetPackageVersion );
#
# # Copy
# Copy-Item `
# -Path $packageFolder `
# -Destination $p.DownloadFolder `
# -Recurse `
# -Force;
# }
#}

#endregion

#region EXPORT

Export-ModuleMember -Function 'Get-Artifact'; 

#endregion