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

Using ANSI escape codes for output #1953

Closed
nohwnd opened this issue May 19, 2021 · 13 comments · Fixed by #2199
Closed

Using ANSI escape codes for output #1953

nohwnd opened this issue May 19, 2021 · 13 comments · Fixed by #2199
Assignees
Milestone

Comments

@nohwnd
Copy link
Member

nohwnd commented May 19, 2021

Using ANSI escape codes would probably also fix output not being colored in CI, which is very unfortunate:

Travis CI

image

https://travis-ci.org/felixfbecker/PSKubectl/jobs/500233965

VSTS

image

https://felixfbecker.visualstudio.com/PowerGit/_build/results?buildId=179

Originally posted by @felixfbecker in #1265 (comment)

@nohwnd
Copy link
Member Author

nohwnd commented May 19, 2021

For perf reasons and because of the redirect issue above make sure we use one write host per line (or less).

@fflaten
Copy link
Collaborator

fflaten commented May 19, 2021

Should I look into this?

Thinking that we would extend OutputConfiguration with a new option. If not set, auto-detect.

Would also limit ANSI-output to the same ConsoleColor-values for now as all VT-terminals doesn't support full RGB.

Could maybe introduce a private Write-PesterHost helper function to avoid if ansi/else-blocks in the code. That is unless the syntax gets too complex. Would need something like a [HostMessage[]]-parameter to support multiple vs single write-host calls I guess.

@nohwnd
Copy link
Member Author

nohwnd commented May 20, 2021

if you are interested in this and see some upside then sure why not. Sure add a function to encapsulate the logic, but probably figure it out at the module load/invoke-pester and then reuse the result? Most, if not all, of the output should be contained the Output.ps1

@asears
Copy link
Contributor

asears commented May 26, 2021

Other than ANSI, color can be controlled via Azure Devops-specific commands. There are not as many color options available as in Output.ps1 themes though.

https://developercommunity.visualstudio.com/t/write-host-foreground-color-with-powershell-task-i/440605

Travis CI has this unbuffer workaround for colorizing output.
travis-ci/travis-ci#7967 (comment)

Kieran Marron posted this example of colorizing the Write-Information output.
https://blog.kieranties.com/2018/03/26/write-information-with-colours

Getting rid of direct calls to Write-Host by first wrapping it with a new Write-PesterHost or Write-HostOutput or Write-TermOutput call would probably be beneficial to Pester framework flexibility with various CI/CD outputs.

@beatcracker
Copy link

beatcracker commented Dec 23, 2021

I'm using my own drop-in replacement for Write-Host to colorize output in CI (Azure DevOps):

I just dot-source it before running anything else and I haven't had any issues yet. Unfortunately it doesn't work with Pester because of the SafeCommands. You might try to embed it, since it would provide an easy way to produce color output. Or at least allow for Write-Host to be overridden, so we can fix it ourselves.

@briantist
Copy link

@beatcracker 's suggestions seem great to me, I would love to be able to get colorized output in GitHub Actions and I think that would do the trick.

@fflaten
Copy link
Collaborator

fflaten commented Apr 18, 2022

That's the idea. The plan is similar, but tried to also merge multiple messages to a single write-host call so we can fix broken redirection of Information-stream.

Btw Pester 5.3 highlights errors in GitHub Actions. So at least they're red atm. 🙂

@briantist
Copy link

That's the idea. The plan is similar, but tried to also merge multiple messages to a single write-host call so we can fix broken redirection of Information-stream.

Btw Pester 5.3 highlights errors in GitHub Actions. So at least they're red atm. 🙂

Nice, is there a PR or some WIP I can follow?

@fflaten
Copy link
Collaborator

fflaten commented Apr 18, 2022

Not yet. Profiled some PoCs when this issue was created, but haven't had time after. Not sure if the stream redirection is worth the perf cost, tried to find the cheapest way.

@briantist
Copy link

Not yet. Profiled some PoCs when this issue was created, but haven't had time after. Not sure if the stream redirection is worth the perf cost, tried to find the cheapest way.

Thanks! A short term change that could be helpful is beatcracker's suggestion of allowing overrides of Write-Host at least. That might not work for every scenario, and that might cause issues with mocking, but it would be something.

@fflaten
Copy link
Collaborator

fflaten commented Apr 18, 2022

There's nothing stopping you from overwriting it already. It is unsupported but as long as you use a parameter-compatible replacement it should work fine. The internal SafeCommands-system is mostly there to avoid unintentional hijacks and only used by internal code. Demo:

function global:mywritehost {
    [CmdletBinding()]
    Param(
        [Parameter(ValueFromPipeline=$true)]
        [Alias('Message')]
        [System.Object[]]$Object,
        [System.Object]$Separator,
        [System.ConsoleColor]$ForegroundColor,
        [System.ConsoleColor]$BackgroundColor,
        [switch]$NoNewline
    )

    Microsoft.PowerShell.Utility\Write-Host -Object "AWESOME - $Object" @PSBoundParameters
}

Import-Module Pester

# Overwrite internal Write-Host reference to point at custom function. Will work until re-import of module
& (Get-Module Pester) { $SafeCommands['Write-Host'] = Get-Command -Type Function -Name mywritehost }

# Test it
Invoke-Pester -Path xyz.tests.ps1 -Output Detailed

There won't be any official way of doing this, especially considering the direct use of Write-Host will be replaced when this feature isse is fixed. You could also use -Output None -Passthru and create your own custom output based on the returned result-object (or wait for plugins to be public so you could replace the output-plugin. tracked in #2021).

@nohwnd
Copy link
Member Author

nohwnd commented Apr 22, 2022

function mywritehost {
    [CmdletBinding()]
    Param(
        [Parameter(ValueFromPipeline=$true)]
        [Alias('Message')]
        [System.Object[]]$Object,
        [System.Object]$Separator,
        [System.ConsoleColor]$ForegroundColor,
        [System.ConsoleColor]$BackgroundColor,
        [switch]$NoNewline
    )

    Microsoft.PowerShell.Utility\Write-Host -Object "AWESOME - $Object" @PSBoundParameters
}

Import-Module Pester

& (Get-Module Pester) { param ($c) $SafeCommands['Write-Host'] = $c } (Get-Command mywritehost)

Commenting just because I am stickler for scoping. That function does not have to be global, you can pass the command info in, and assign it. 🙂

@briantist
Copy link

Indeed @nohwnd , I did not end up using a global 😆 though in my case I simply dot sourced within the module's runspace.
https://github.com/briantist/CcgVault/pull/5/files#diff-99dcb0298ba2b59c1cb805648abc6cd9ac0e8b732fa9dda7a8607b4676343244

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants