Search code examples
visual-studio-codecommand-linecross-platformdevelopment-environmentvscode-devcontainer

How to create a cross-platform initializeCommand for Visual Studio Code's Dev Container?


Let's assume that I have:

  • .env file which is .gitignored
  • .env.dev.dist etc. kind of files to copy to .env for each environment and fill in some more secret variables that are blank by default
  • devcontainer.json that is supposed to be as automated as possible, so I'd like at the very least to copy .env.dev.dist file to .env if it doesn't exist yet and open the copied .env in VSCode

I saw there's initializeCommand option for devcontainer.json that could help with that as it runs on the host before containers are initialized. However, I don't see how I could possibly create a script that would work on all systems, as syntax for mentioned task(s) differs between them.

Any option I'm missing to define separate commands per system?

Also, reference to a similar unanswered question that has a bit different main question: Is there a way to automate the creation of a file needed by a container in VS Code Remote-Containers before it runs?


Solution

  • Install make on both platforms

    # for windows use chocolatey
    choco install -y make
    
    # if you want powershell-core
    choco install -y powershell-core
    
    

    and use that to choose the correct calls to make:

    ifeq ($(OS),Windows_NT)
      INITIALIZERS=initialize-windows
    else
      INITIALIZERS=initialize-linux
    endif
    
    ifneq (, $(shell which pwsh))
        SHELL_COMMAND=pwsh
    else ifneq (, $(shell which powershell))
        SHELL_COMMAND=powershell
    endif
    
    initialize: $(INITIALIZERS) .env
    
    .env:
        cp .env.dev.dist .env
    
    initialize-windows:
        @echo "Initializing Windows..."
        $(SHELL_COMMAND) -File .devcontainer/setup-ssh-agent.ps1
    
    initialize-linux:
        @echo "Initializing Linux..."
    
    

    call from .devcontainer/devcontainer.json with:

    "initializeCommand": "make initialize --ignore-errors -f .devcontainer/Makefile",
    

    and here is the script that's referenced if anyone is interested: setup-ssh-agent.ps1

    if ($(Get-Service -Name ssh-agent).Status -ne 'Running')
    {   
        # https://stackoverflow.com/a/57035712/1973777
        if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
            Start-Process PowerShell -Verb RunAs "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
            exit;
        }
    
        Set-Service ssh-agent -StartupType Automatic
        Start-Service ssh-agent
        Write-Output "SSH-Agent Started..."
    }
    else
    {
        Write-Output "SSH-Agent Already Running..."
    }