Skip to content

Enable PowerShell Core support in Docker Executor on Linux

Description

The Docker Executor currently supports running commands from bash and sh (sources: here and here). Microsoft has been doing a whole lot of work over the past few years and have built the current version of PowerShell to run not only on Windows, but various Linux distributions and macOS, as well. However, when a Linux Docker image with PowerShell as the default shell is specified for a CI job, GitLab Runner forcefully uses bash or sh to run the commands specified in the job's script, e.g. Write-Output $PSVersionTable . There are workarounds, including a) wrapping each PowerShell command so that PowerShell will run it, e.g. pwsh -Command { Write-Output $PSVersionTable } and b) writing your job as a .ps1 script and executing the script using PowerShell, e.g. pwsh -File ./gitlab-ci-job.ps1 (this approach has caveats that now the source code must be checked out for the job to run and the PowerShell script has to internally manage the exit code return (usually done by GitLab)).

My specific use case is trying to deploy build artifacts from previous jobs to a Windows machine. I've built a container (yes, it's a bit undocumented and quick/dirty)(shawmanz32na/ssh-powershell-client) that uses PowerShell by default (launching the container drops you in a PowerShell prompt). A sample CI job to use this container is:

deploy_qa:
  stage: deploy
  dependencies:
    - build
  image: shawmanz32na/ssh-powershell-client
  script:
    - $remoteSession = New-PSSession -HostName "the.qa.machine" -UserName "theDeploymentUser"
    - Copy-Item -Path path/to/build/job.artifact -Destination C:/Users/theDeploymentUser/Local/Temp -ToSession $remoteSession
    - Remove-PSSession -Session $remoteSession

This script explodes with syntax errors and/or reporting that New-PSSession isn't a valid command/script/executable.

A simpler reproducible case is:

sample_job:
  image: shawmanz32na/ssh-powershell-client
  script:
    - Write-Output $PSVersionTable

This script will also fail with messages that Write-Output isn't a command/script/executable. Were it to succeed, it would print out the running PowerShell edition and version.

Proposal

  • Have docker executor choose between pwsh and bash depending on the user config.toml. We need to remove any assumptions we have that we are using a bash shell.
  • Update the linux helper image to have pwsh installed. There are several consider things to consider:
    • Powershell Core 7 does not support all the platforms that the gitlab-runner-helper supports, namely arm64, alpine arm, or s390x.
    • How much of size increase there would be by having pwsh installed since this container is used multiple times.
    • Based on the 2 points above, it might be worth having a separate image just for pwsh and then have the executor chooses the right image based on the shell requested.
      • Update ci/build_helper_docker to create an additional Alpine Linux amd64 image (based on the regular one) that includes Powershell Core 7 installed (e.g. dockerfiles/runner-helper/Dockerfile.pwsh.x86_64.
      • Only address x86_64 for now and leave other platforms for future iterations, based on demand.
  • Somehow update gitlab-runner-build or the usage of it to support both bash and pwsh so it doesn't mess up helper image commands.

Links to related issues and merge requests / references

Edited by Pedro Pombeiro