Skip to content
Open
17 changes: 16 additions & 1 deletion src/powershell/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "powershell",
"version": "2.0.2",
"version": "2.0.3",
"name": "PowerShell",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/powershell",
"description": "Installs PowerShell along with needed dependencies. Useful for base Dockerfiles that often are missing required install dependencies like gpg.",
Expand Down Expand Up @@ -28,6 +28,11 @@
"type": "string",
"default": "",
"description": "Optional (publicly accessible) URL to download PowerShell profile."
},
"preserveHistory": {
"type": "boolean",
"default": true,
"description": "Optional Enable to preserve the powershell history across container restart/rebuilds"
}
},
"customizations": {
Expand All @@ -44,6 +49,16 @@
]
}
},
"mounts": [
{
"type": "volume",
"source": "${devcontainerId}-powershell-history",
"target": "/dc/powershell"
}
],
"onCreateCommand": {
"powershell": "/usr/local/share/powershell/scripts/oncreate.sh"
},
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
Expand Down
30 changes: 29 additions & 1 deletion src/powershell/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@

set -e

# Capture the location of this script once so later directory changes do not affect relative file lookups.
SOURCE_DIR="$(pwd)"

# Clean up
rm -rf /var/lib/apt/lists/*

POWERSHELL_VERSION=${VERSION:-"latest"}
POWERSHELL_MODULES="${MODULES:-""}"
POWERSHELL_PROFILE_URL="${POWERSHELLPROFILEURL}"
PRESERVE_HISTORY="${PRESERVEHISTORY}"

MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc"
#MICROSOFT_GPG_KEYS_URI=$(curl https://packages.microsoft.com/keys/microsoft.asc -o /usr/share/keyrings/microsoft-archive-keyring.gpg)
Expand Down Expand Up @@ -494,7 +498,31 @@ if [ -n "$POWERSHELL_PROFILE_URL" ]; then
echo "Downloading PowerShell Profile from: $POWERSHELL_PROFILE_URL"
# Get profile path from currently installed pwsh
profilePath=$(pwsh -noni -c '$PROFILE.AllUsersAllHosts')
sudo -E curl -sSL -o "$profilePath" "$POWERSHELL_PROFILE_URL"
# Download to a temp file first so a non-200 response never overwrites the profile
tmpProfile="$(mktemp)"
http_status=$(curl -sSL -w '%{http_code}' -o "$tmpProfile" "$POWERSHELL_PROFILE_URL")
if [ "$http_status" = "200" ]; then
mv "$tmpProfile" "$profilePath"
chmod 0664 "$profilePath"
else
echo "Failed to download PowerShell profile (HTTP ${http_status}). Skipping profile update." >&2
rm -f "$tmpProfile"
fi
fi

# Copy persistent history setup script
ONCREATE_SOURCE="${SOURCE_DIR}/oncreate.sh"
SCRIPTS_DIR="/usr/local/share/powershell/scripts"
mkdir -p "$SCRIPTS_DIR"
echo "Checking oncreate.sh"
if [ ! -f "$ONCREATE_SOURCE" ]; then
echo "oncreate.sh not found at expected path: $ONCREATE_SOURCE" >&2
exit 1
fi
if [ -f "$ONCREATE_SOURCE" ]; then
cp "$ONCREATE_SOURCE" "$SCRIPTS_DIR/oncreate.sh"
sed -i "s|preserveHistoryFromInstallSh|${PRESERVE_HISTORY}|" "$SCRIPTS_DIR/oncreate.sh"
chmod +x "$SCRIPTS_DIR/oncreate.sh"
fi

# Clean up
Expand Down
24 changes: 24 additions & 0 deletions src/powershell/oncreate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -e

PRESERVE_HISTORY="preserveHistoryFromInstallSh"
HISTORY_SAVE_LINE='Set-PSReadLineOption -HistorySavePath /dc/powershell/history.txt'

if [ "${PRESERVE_HISTORY}" = "true" ]; then
if [ "$(stat -c '%u:%g' "/dc/powershell")" = "$(id -u):$(id -g)" ]; then
echo "Already owned by the current user, nothing to do"
elif [ "$(id -u)" -eq 0 ]; then
chown -R "$(id -u):$(id -g)" "/dc/powershell"
elif command -v sudo >/dev/null 2>&1; then
sudo chown -R "$(id -u):$(id -g)" "/dc/powershell"
else
echo "Warning: unable to chown /dc/powershell (current user not root and no sudo available); history may not persist." >&2
fi
profile_path="$(pwsh -NoProfile -Command '$PROFILE')"
mkdir -p "$(dirname "$profile_path")"
touch "$profile_path"

if ! grep -Fxq "$HISTORY_SAVE_LINE" "$profile_path"; then
printf '\n%s\n' "$HISTORY_SAVE_LINE" >> "$profile_path"
fi
fi
2 changes: 1 addition & 1 deletion test/powershell/install_modules.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ check "pwsh version is LTS (not preview)" bash -c "pwsh --version | grep -v 'pre
# Extension-specific tests
check "az.resources" pwsh -Command "(Get-Module -ListAvailable -Name Az.Resources).Version.ToString()"
check "az.storage" pwsh -Command "(Get-Module -ListAvailable -Name Az.Storage).Version.ToString()"
check "profile" pwsh -Command "(Get-Variable $env:ProfileLoaded).Value"
check "profile" pwsh -Command 'if (-not $env:ProfileLoaded) {Write-Host "Profile not loaded, envvar '\''ProfileLoaded'\'' does not exist"; exit 1 } else {Write-Host "Profile Loaded: $($env:ProfileLoaded)"; exit 0 }'

# Report result
reportResults
Loading