Skip to content
Merged
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
entry point for all
operations.
- Change `nova` help to a dedicated CLI-native help system with both short and long command help forms.
- Isolate external workflow execution behind smaller internal adapters so git, raw package upload, repository publish,
self-update, settings-file I/O, and CLI environment access have clearer change points and smaller test seams.
- `% nova <command> --help` and `% nova <command> -h` now show short CLI help.
- `% nova --help <command>` and `% nova -h <command>` now show long CLI help.
- Long command help now includes the matching public GitHub Pages guide URL for the selected command, while short help
Expand Down
28 changes: 24 additions & 4 deletions src/private/cli/ConfirmNovaCliAction.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,15 @@ function Invoke-NovaCliConsoleReadKey {
[CmdletBinding()]
param()

return [Console]::ReadKey($true)
$consoleReader = Get-NovaCliConsoleReadKeyReader
return & $consoleReader
}

function Get-NovaCliConsoleReadKeyReader {
[CmdletBinding()]
param()

return {[Console]::ReadKey($true)}
}

function Read-NovaCliPromptKey {
Expand All @@ -52,14 +60,27 @@ function Read-NovaCliPromptKey {
}
}

function Get-NovaCliConfirmResponseKey {
[CmdletBinding()]
param()

$response = Get-NovaEnvironmentVariableValue -Name 'NOVA_CLI_CONFIRM_RESPONSE'
if ( [string]::IsNullOrWhiteSpace($response)) {
return $null
}

return [char]$response[0]
}

function Get-NovaCliCommandPromptKey {
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$Message
)

if (-not [string]::IsNullOrWhiteSpace($env:NOVA_CLI_CONFIRM_RESPONSE)) {
return [char]$env:NOVA_CLI_CONFIRM_RESPONSE[0]
$configuredResponse = Get-NovaCliConfirmResponseKey
if ($null -ne $configuredResponse) {
return $configuredResponse
}

Write-Host 'Confirm'
Expand Down Expand Up @@ -127,4 +148,3 @@ function Confirm-NovaCliCommandAction {
return
} while ($true)
}

2 changes: 1 addition & 1 deletion src/private/cli/GetNovaCliInstallDirectory.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ function Get-NovaCliInstallDirectory {
return [System.IO.Path]::GetFullPath($DestinationDirectory)
}

$homeDirectory = $env:HOME
$homeDirectory = Get-NovaEnvironmentVariableValue -Name 'HOME'

if ( [string]::IsNullOrWhiteSpace($homeDirectory)) {
Stop-NovaOperation -Message 'HOME environment variable is not set. Provide -DestinationDirectory explicitly.' -ErrorId 'Nova.Environment.HomeDirectoryMissing' -Category ResourceUnavailable -TargetObject 'HOME'
Expand Down
3 changes: 2 additions & 1 deletion src/private/cli/TestNovaCliDirectoryOnPath.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ function Test-NovaCliDirectoryOnPath {
)

$resolvedDirectory = [System.IO.Path]::GetFullPath($Directory)
foreach ($entry in @($env:PATH -split [regex]::Escape([string][System.IO.Path]::PathSeparator))) {
$pathValue = Get-NovaEnvironmentVariableValue -Name 'PATH'
foreach ($entry in @($pathValue -split [regex]::Escape([string][System.IO.Path]::PathSeparator))) {
if ( [string]::IsNullOrWhiteSpace($entry)) {
continue
}
Expand Down
16 changes: 1 addition & 15 deletions src/private/package/InvokeNovaPackageArtifactUpload.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,8 @@ function Invoke-NovaPackageArtifactUpload {
Stop-NovaOperation -Message "Package file not found: $( $UploadArtifact.PackagePath )" -ErrorId 'Nova.Environment.PackageUploadFileNotFound' -Category ObjectNotFound -TargetObject $UploadArtifact.PackagePath
}

$webRequestParameters = @{
Uri = $UploadArtifact.UploadUrl
Method = 'Put'
InFile = $UploadArtifact.PackagePath
}
if (@($UploadArtifact.Headers.Keys).Count -gt 0) {
$webRequestParameters.Headers = $UploadArtifact.Headers
}

$webRequestCommand = Get-Command -Name Invoke-WebRequest -CommandType Cmdlet -ErrorAction Stop
if ( $webRequestCommand.Parameters.ContainsKey('UseBasicParsing')) {
$webRequestParameters.UseBasicParsing = $true
}

try {
$response = Invoke-WebRequest @webRequestParameters
$response = Invoke-NovaPackageUploadRequest -UploadArtifact $UploadArtifact
}
catch {
Stop-NovaOperation -Message "Package upload failed for $( $UploadArtifact.PackagePath ) -> $( $UploadArtifact.UploadUrl ). $( $_.Exception.Message )" -ErrorId 'Nova.Dependency.PackageUploadRequestFailed' -Category ConnectionError -TargetObject $UploadArtifact.UploadUrl
Expand Down
42 changes: 42 additions & 0 deletions src/private/package/InvokeNovaPackageUploadRequest.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
function Get-NovaPackageUploadRequestParameterMap {
[CmdletBinding()]
param(
[Parameter(Mandatory)][pscustomobject]$UploadArtifact
)

$parameters = @{
Uri = $UploadArtifact.UploadUrl
Method = 'Put'
InFile = $UploadArtifact.PackagePath
}
if (@($UploadArtifact.Headers.Keys).Count -gt 0) {
$parameters.Headers = $UploadArtifact.Headers
}

return $parameters
}

function Add-NovaLegacyWebRequestOption {
[CmdletBinding()]
param(
[Parameter(Mandatory)][hashtable]$Parameters
)

$webRequestCommand = Get-Command -Name Invoke-WebRequest -CommandType Cmdlet -ErrorAction Stop
if ( $webRequestCommand.Parameters.ContainsKey('UseBasicParsing')) {
$Parameters.UseBasicParsing = $true
}

return $Parameters
}

function Invoke-NovaPackageUploadRequest {
[CmdletBinding()]
param(
[Parameter(Mandatory)][pscustomobject]$UploadArtifact
)

$parameters = Get-NovaPackageUploadRequestParameterMap -UploadArtifact $UploadArtifact
$parameters = Add-NovaLegacyWebRequestOption -Parameters $parameters
return Invoke-WebRequest @parameters
}
34 changes: 26 additions & 8 deletions src/private/release/GetGitCommitMessagesForVersionBump.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,38 @@ function Get-GitCommitMessageForVersionBump {
}

$format = '%s%n%b%n--END-COMMIT--'
$lastTag = & git -C $ProjectRoot describe --tags --abbrev=0 2> $null
$lastTagResult = Invoke-NovaGitCommand -ProjectRoot $ProjectRoot -Arguments @('describe', '--tags', '--abbrev=0')
$logResult = Get-NovaVersionBumpCommitLogResult -ProjectRoot $ProjectRoot -Format $format -LastTagResult $lastTagResult
return @(ConvertFrom-NovaVersionBumpCommitLogResult -Result $logResult)
}

if ($LASTEXITCODE -eq 0 -and -not [string]::IsNullOrWhiteSpace($lastTag)) {
$raw = & git -C $ProjectRoot log "$lastTag..HEAD" --format=$format 2> $null
}
else {
$raw = & git -C $ProjectRoot log --format=$format 2> $null
function Get-NovaVersionBumpCommitLogResult {
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$ProjectRoot,
[Parameter(Mandatory)][string]$Format,
[Parameter(Mandatory)][pscustomobject]$LastTagResult
)

$lastTag = Get-NovaGitCommandOutputText -Result $LastTagResult
if ($LastTagResult.ExitCode -eq 0 -and -not [string]::IsNullOrWhiteSpace($lastTag)) {
return Invoke-NovaGitCommand -ProjectRoot $ProjectRoot -Arguments @('log', "$lastTag..HEAD", "--format=$format")
}

if ($LASTEXITCODE -ne 0 -or -not $raw) {
return Invoke-NovaGitCommand -ProjectRoot $ProjectRoot -Arguments @('log', "--format=$format")
}

function ConvertFrom-NovaVersionBumpCommitLogResult {
[CmdletBinding()]
param(
[Parameter(Mandatory)][pscustomobject]$Result
)

if ($Result.ExitCode -ne 0 -or @($Result.Output).Count -eq 0) {
return @()
}

$text = ($raw -join [Environment]::NewLine)
$text = (@($Result.Output) -join [Environment]::NewLine)
$commits = $text -split '(?m)^--END-COMMIT--\r?$'
return @($commits | ForEach-Object {$_.Trim()} | Where-Object {-not [string]::IsNullOrWhiteSpace($_)})
}
18 changes: 10 additions & 8 deletions src/private/release/GetNovaVersionLabelForBump.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ function Test-GitRepositoryIsAvailable {
return $false
}

$null = & git -C $ProjectRoot rev-parse --git-dir 2> $null
return $LASTEXITCODE -eq 0
$result = Invoke-NovaGitCommand -ProjectRoot $ProjectRoot -Arguments @('rev-parse', '--git-dir')
return $result.ExitCode -eq 0
}

function Test-GitRepositoryHasCommittedHead {
Expand All @@ -44,8 +44,8 @@ function Test-GitRepositoryHasCommittedHead {
[Parameter(Mandatory)][string]$ProjectRoot
)

$null = & git -C $ProjectRoot rev-parse --verify HEAD 2> $null
return $LASTEXITCODE -eq 0
$result = Invoke-NovaGitCommand -ProjectRoot $ProjectRoot -Arguments @('rev-parse', '--verify', 'HEAD')
return $result.ExitCode -eq 0
}

function Test-GitRepositoryHasCommitsSinceLatestTag {
Expand All @@ -54,11 +54,13 @@ function Test-GitRepositoryHasCommitsSinceLatestTag {
[Parameter(Mandatory)][string]$ProjectRoot
)

$lastTag = & git -C $ProjectRoot describe --tags --abbrev=0 2> $null
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($lastTag)) {
$lastTagResult = Invoke-NovaGitCommand -ProjectRoot $ProjectRoot -Arguments @('describe', '--tags', '--abbrev=0')
$lastTag = Get-NovaGitCommandOutputText -Result $lastTagResult
if ($lastTagResult.ExitCode -ne 0 -or [string]::IsNullOrWhiteSpace($lastTag)) {
return $true
}

$commitCount = & git -C $ProjectRoot rev-list --count "$lastTag..HEAD" 2> $null
return $LASTEXITCODE -ne 0 -or $commitCount -ne '0'
$commitCountResult = Invoke-NovaGitCommand -ProjectRoot $ProjectRoot -Arguments @('rev-list', '--count', "$lastTag..HEAD")
$commitCount = Get-NovaGitCommandOutputText -Result $commitCountResult
return $commitCountResult.ExitCode -ne 0 -or $commitCount -ne '0'
}
58 changes: 35 additions & 23 deletions src/private/release/InitiateGitRepo.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,44 @@ function New-InitiateGitRepo {
[string]$DirectoryPath
)

# Check if Git is installed
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
Write-Warning 'Git is not installed. Please install Git and initialize repo manually'
if (-not (Test-NovaGitCommandAvailable)) {
Write-Warning 'Git is not installed. Please install Git and initialize repo manually'
return
}
Push-Location -StackName 'GitInit'

if (Test-Path -LiteralPath (Join-Path $DirectoryPath '.git')) {
Write-Warning 'A Git repository already exists in this directory.'
return
}

if (-not $PSCmdlet.ShouldProcess($DirectoryPath, "Initiating git on $DirectoryPath")) {
return
}

try {
# Navigate to the specified directory
Set-Location $DirectoryPath

# Check if a Git repository already exists
if (Test-Path -Path '.git') {
Write-Warning 'A Git repository already exists in this directory.'
return
}

if ( $PSCmdlet.ShouldProcess($DirectoryPath, ("Initiating git on $DirectoryPath"))) {
try {
git init | Out-Null
} catch {
Stop-NovaOperation -Message "Failed to initialize Git repo: $( $_.Exception.Message )" -ErrorId 'Nova.Dependency.GitRepositoryInitializationFailed' -Category OpenError -TargetObject $DirectoryPath
}
}
Write-Verbose 'Git repository initialized successfully'
$result = Invoke-NovaGitCommand -ProjectRoot $DirectoryPath -Arguments @('init')
}
finally {
Pop-Location -StackName 'GitInit'
catch {
Stop-NovaOperation -Message "Failed to initialize Git repo: $( $_.Exception.Message )" -ErrorId 'Nova.Dependency.GitRepositoryInitializationFailed' -Category OpenError -TargetObject $DirectoryPath
}

if ($result.ExitCode -ne 0) {
Stop-NovaOperation -Message (Get-NovaGitInitializationFailureMessage -Result $result) -ErrorId 'Nova.Dependency.GitRepositoryInitializationFailed' -Category OpenError -TargetObject $DirectoryPath
}

Write-Verbose 'Git repository initialized successfully'
}

function Get-NovaGitInitializationFailureMessage {
[CmdletBinding()]
param(
[Parameter(Mandatory)][pscustomobject]$Result
)

$details = Get-NovaGitCommandOutputText -Result $Result
if ( [string]::IsNullOrWhiteSpace($details)) {
return 'Failed to initialize Git repo.'
}

return "Failed to initialize Git repo: $details"
}
8 changes: 8 additions & 0 deletions src/private/release/InvokeNovaRepositoryPublishCommand.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
function Invoke-NovaRepositoryPublishCommand {
[CmdletBinding()]
param(
[Parameter(Mandatory)][hashtable]$PublishParameters
)

Publish-PSResource @PublishParameters
}
39 changes: 25 additions & 14 deletions src/private/release/PublishNovaBuiltModuleToRepository.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,29 @@ function Get-NovaPublishRepositoryDefaultApiKeyEnvironmentVariable {
return $null
}

function Get-NovaRepositoryPublishParameterMap {
[CmdletBinding()]
param(
[Parameter(Mandatory)][pscustomobject]$ProjectInfo,
[Parameter(Mandatory)][string]$Repository,
[string]$ApiKey,
[Parameter(Mandatory)][bool]$VerboseRequested
)

$publishParams = @{
Path = $ProjectInfo.OutputModuleDir
Repository = $Repository
}
if ($VerboseRequested) {
$publishParams.Verbose = $true
}
if (-not [string]::IsNullOrWhiteSpace($ApiKey)) {
$publishParams.ApiKey = $ApiKey
}

return $publishParams
}

function Publish-NovaBuiltModuleToRepository {
[CmdletBinding(SupportsShouldProcess = $true)]
param(
Expand All @@ -27,23 +50,11 @@ function Publish-NovaBuiltModuleToRepository {
ExplicitValue = $ApiKey
DefaultEnvironmentVariableName = Get-NovaPublishRepositoryDefaultApiKeyEnvironmentVariable -Repository $Repository
})

$publishParams = @{
Path = $ProjectInfo.OutputModuleDir
Repository = $Repository
}

if ( $PSBoundParameters.ContainsKey('Verbose')) {
$publishParams.Verbose = $true
}

if (-not [string]::IsNullOrWhiteSpace($resolvedApiKey)) {
$publishParams.ApiKey = $resolvedApiKey
}
$publishParams = Get-NovaRepositoryPublishParameterMap -ProjectInfo $ProjectInfo -Repository $Repository -ApiKey $resolvedApiKey -VerboseRequested:$PSBoundParameters.ContainsKey('Verbose')

if (-not $PSCmdlet.ShouldProcess($Repository, 'Publish built module to repository')) {
return
}

Publish-PSResource @publishParams
Invoke-NovaRepositoryPublishCommand -PublishParameters $publishParams
}
29 changes: 29 additions & 0 deletions src/private/shared/InvokeNovaGitCommand.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
function Test-NovaGitCommandAvailable {
[CmdletBinding()]
param()

return $null -ne (Get-Command -Name 'git' -ErrorAction SilentlyContinue)
}

function Invoke-NovaGitCommand {
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$ProjectRoot,
[Parameter(Mandatory)][string[]]$Arguments
)

$output = & git -C $ProjectRoot @Arguments 2> $null
return [pscustomobject]@{
ExitCode = $LASTEXITCODE
Output = @($output)
}
}

function Get-NovaGitCommandOutputText {
[CmdletBinding()]
param(
[Parameter(Mandatory)][pscustomobject]$Result
)

return (@($Result.Output) -join [Environment]::NewLine).Trim()
}
Loading
Loading