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

feat: powershell toolbox improvements #94

Merged
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@ Centralized repository of containers designed for Toolbox/Distrobox with batteri
- `fedora-toolbox` - a Fedora base image
- `wolfi-toolbox` - a WolfiOS base image
- `bluefin-cli` - a WolfiOS based image with Homebrew and a strongly opinionated default experience
- `powershell-toolbox` - a WolfiOS based image with PowerShell and other Microsoft related tooling

It is strongly recommended that the [Prompt terminal](https://gitlab.gnome.org/chergert/prompt) be used with these toolboxes and is the default experience in both [Bazzite](https://bazzite.gg) and [Bluefin](https://projectbluefin.io).
It is strongly recommended that the [Ptyxis terminal](https://gitlab.gnome.org/chergert/ptyxis) be used with these toolboxes and is the default experience in both [Bazzite](https://bazzite.gg) and [Bluefin](https://projectbluefin.io).

## Automatic Toolbox Startup

### Quadlets

Podman supports starting containers via a systemd generator. Quadlets replaced the `podman generate systemd` command and provide a method to create a systemd service for managing your container. The generated unit file can automatically start your container on login, automatically check for updates from the registry, and automatically clean-up the container and any transient volumes when the container stops. This provides an ideal way to have a clean slate on each login.

Inside the quadlets directory are example quadlets each of the toolboxes listed above. Distrobox and Toolbox provide a convenient way to integrate the containers into your host.`ubuntu-toolbox` and `fedora-toolbox` can use either toolbox or distrobox. `wolfi-toolbox` and `bluefin-cli` are currently only compatible with distrobox.
Inside the quadlets directory are example quadlets each of the toolboxes listed above. Distrobox and Toolbox provide a convenient way to integrate the containers into your host.`ubuntu-toolbox` and `fedora-toolbox` can use either toolbox or distrobox. `wolfi-toolbox`, `bluefin-cli` and `powershell-toolbox` (WolfiOS base) are currently only compatible with distrobox.

The quadlets mimic the create and enter commands to setup the container. You can use these by copying them to `~/.config/containers/systemd`. When using the Prompt terminal, they will appear in the menu as available containers. The `Exec=` line of the distrobox quadlets can be modified to include additional packages.

Expand All @@ -38,20 +39,24 @@ To utilize these, place the user service file in `~/.config/systemd/user` and ma

### Bluefin-CLI

`bluefin-cli` is built from `wolfi-toolbox`. It contains [Homebrew](https://brew.sh/) configured out of the box. The brew state is bind mounted to a directory from your `$HOME`. Unlike the other toolboxes, `bluefin-cli` is intended for CLI applications _only_.
`bluefin-cli` is built from `wolfi-toolbox`. It contains [Homebrew](https://brew.sh/) configured out of the box. The brew state is bind mounted to a directory from your `$HOME`. Unlike the other toolboxes, `bluefin-cli` is intended for CLI applications _only_.

It's primary purpose is to be **the** command line companion to Flathub-enabled systems by providing access to one of the largest command line repositories in the world via homebrew. Developer dependencies should be managed seperately via [devcontainers](https://github.com/devcontainers).
Its primary purpose is to be **the** command line companion to Flathub-enabled systems by providing access to one of the largest command line repositories in the world via homebrew. Developer dependencies should be managed seperately via [devcontainers](https://github.com/devcontainers).

The default configuration destroys and updates this container daily so that the toolbox is built from scratch.

Updates to brew itself happen automatically when the container rebuilds. Brew will automatically upgrade packages as you use it. Brew's state is also volume mounted to a file in your home directory so your container is fresh but your packages remain untouched. At this time it is **strongly recommended** to maintain a backup of your brew package list via the [brew bundle](https://docs.brew.sh/Manpage#bundle-subcommand) subcommand.
Updates to brew itself happen automatically when the container rebuilds. Brew will automatically upgrade packages as you use it. Brew's state is also volume mounted to a file in your home directory so your container is fresh but your packages remain untouched. At this time it is **strongly recommended** to maintain a backup of your brew package list via the [brew bundle](https://docs.brew.sh/Manpage#bundle-subcommand) subcommand.

The [WolfiOS](https://edu.chainguard.dev/open-source/wolfi/overview/) apk package manager is preferred for fully declarative setups with [boxkit](https://github.com/ublue-os/boxkit). You can file package requests on the [WolfiOS repository](https://github.com/wolfi-dev/) for packages that you may need. We are working on a way to do this locally as well.
The [WolfiOS](https://edu.chainguard.dev/open-source/wolfi/overview/) apk package manager is preferred for fully declarative setups with [boxkit](https://github.com/ublue-os/boxkit). You can file package requests on the [WolfiOS repository](https://github.com/wolfi-dev/) for packages that you may need. We are working on a way to do this locally as well.

The intended endstate of `bluefin-cli` is a fully automated declarative config managed via git using Wolfi packages for clean rebuilds daily. `brew` is used to fill out the "long tail" of existing software.

Both `bluefin-cli` and `wolfi-toolbox` have Wolfi developer variants built from the Wolfi SDK image, intended for Wolfi package and image development. They include utilities such as melange, wolfictl, and apko. These images are labelled `bluefin-dx-cli` and `wolfi-dx-toolbox`.

### PowerShell-Toolbox

`powershell-toolbox` is based on `WolfiOS`. Its primary purpose is to be a dedicated container for Microsoft related technologies used during development. It contains [PowerShell](https://github.com/PowerShell/PowerShell), [Azure CLI](https://github.com/Azure/azure-cli) and [.NET](https://github.com/dotnet/core) (latest LTS) configured out of the box. It also includes a small selection of other useful CLI utilities to improve the overall experience.

# Stats

## Star History
Expand Down
29 changes: 21 additions & 8 deletions toolboxes/powershell-toolbox/Containerfile.powershell
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,30 @@ LABEL com.github.containers.toolbox="true" \
usage="This image is meant to be used with the toolbox or distrobox command" \
description="A container image with integrated Powershell and Microsoft tooling for development environments."

# COPY ./toolboxes/powershell-toolbox/packages.powershell /tmp
COPY packages.powershell /tmp
ENV POWERSHELL_TELEMETRY_OPTOUT=1
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1

# COPY packages.powershell /tmp
# COPY profile.ps1 /tmp/Microsoft.PowerShell_profile.ps1
COPY ./toolboxes/powershell-toolbox/packages.powershell /tmp
COPY ./toolboxes/powershell-toolbox/profile.ps1 /tmp/Microsoft.PowerShell_profile.ps1

SHELL ["/bin/ash", "-eo", "pipefail", "-c"]

RUN apk upgrade && \
grep -v '^#' /tmp/packages.powershell | xargs apk add --no-cache
RUN apk upgrade \
&& grep -v '^#' /tmp/packages.powershell | xargs apk add --no-cache \
&& dotnet tool install --global PowerShell \
&& az config set core.collect_telemetry=no \
&& curl -s https://ohmyposh.dev/install.sh | bash -s \
&& curl -LSfs https://raw.githubusercontent.com/cantino/mcfly/master/ci/install.sh | sh -s -- --git cantino/mcfly \
&& mkdir -p ~/.config/powershell \
&& cp /tmp/Microsoft.PowerShell_profile.ps1 ~/.config/powershell \
&& mkdir -p ~/.local/share/powershell/PSReadLine \
&& touch ~/.local/share/powershell/PSReadLine/ConsoleHost_history.txt \
&& rm -rf /tmp/*

ENV DOTNET_TOOLS=~/.dotnet/tools
ENV PATH=${DOTNET_TOOLS}:${PATH}

ENV POWERSHELL_TELEMETRY_OPTOUT=1
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1

RUN az config set core.collect_telemetry=no && \
rm -rf /tmp/*

10 changes: 9 additions & 1 deletion toolboxes/powershell-toolbox/packages.powershell
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
az
bat
dotnet-8-sdk
powershell
eza
fd
fzf
gawk
jq
ripgrep
sed
zoxide
64 changes: 64 additions & 0 deletions toolboxes/powershell-toolbox/profile.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Oh My Posh
oh-my-posh init pwsh --config 'https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/mt.omp.json' | Invoke-Expression

Check warning on line 2 in toolboxes/powershell-toolbox/profile.ps1

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

toolboxes/powershell-toolbox/profile.ps1#L2

Invoke-Expression is used. Please remove Invoke-Expression from script and find other options instead.

# Zoxide
Invoke-Expression (& { (zoxide init powershell | Out-String) })

Check warning on line 5 in toolboxes/powershell-toolbox/profile.ps1

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

toolboxes/powershell-toolbox/profile.ps1#L5

Invoke-Expression is used. Please remove Invoke-Expression from script and find other options instead.

# PSReadLine
if ((Get-InstalledModule `

Check warning on line 8 in toolboxes/powershell-toolbox/profile.ps1

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

toolboxes/powershell-toolbox/profile.ps1#L8

$null should be on the left side of equality comparisons.
-Name "PSReadLine" `
-ErrorAction SilentlyContinue) -eq $null) {

Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
Install-Module -Name PSReadLine -AllowPrerelease -Force
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Untrusted
}

# PSFzf
if ((Get-InstalledModule `
-Name "PSFzf" `
-ErrorAction SilentlyContinue) -eq $null) {

Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
Install-Module -Name PSFzf
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Untrusted
}

# Set PSReadLine options to show the history of typed commands
Set-PSReadLineOption -PredictionSource History
Set-PSReadLineOption -PredictionViewStyle ListView
Set-PSReadLineOption -EditMode Windows

# Set shortcuts to begin fzf searching
Set-PsFzfOption -PSReadlineChordProvider 'Ctrl+t' -PSReadlineChordReverseHistory 'Ctrl+f'

# McFly
Invoke-Expression -Command $(mcfly init powershell | Out-String)

Check warning on line 36 in toolboxes/powershell-toolbox/profile.ps1

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

toolboxes/powershell-toolbox/profile.ps1#L36

Invoke-Expression is used. Please remove Invoke-Expression from script and find other options instead.
# $env:MCFLY_LIGHT = "TRUE"

# PowerShell parameter completion shim for the dotnet CLI
Register-ArgumentCompleter -Native -CommandName dotnet -ScriptBlock {
param($commandName, $wordToComplete, $cursorPosition)
dotnet complete --position $cursorPosition "$wordToComplete" | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}

# PowerShell parameter completion shim for Azure CLI
Register-ArgumentCompleter -Native -CommandName az -ScriptBlock {
param($commandName, $wordToComplete, $cursorPosition)
$completion_file = New-TemporaryFile
$env:ARGCOMPLETE_USE_TEMPFILES = 1
$env:_ARGCOMPLETE_STDOUT_FILENAME = $completion_file
$env:COMP_LINE = $wordToComplete
$env:COMP_POINT = $cursorPosition
$env:_ARGCOMPLETE = 1
$env:_ARGCOMPLETE_SUPPRESS_SPACE = 0
$env:_ARGCOMPLETE_IFS = "`n"
$env:_ARGCOMPLETE_SHELL = 'powershell'
az 2>&1 | Out-Null
Get-Content $completion_file | Sort-Object | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, "ParameterValue", $_)
}
Remove-Item $completion_file, Env:\_ARGCOMPLETE_STDOUT_FILENAME, Env:\ARGCOMPLETE_USE_TEMPFILES, Env:\COMP_LINE, Env:\COMP_POINT, Env:\_ARGCOMPLETE, Env:\_ARGCOMPLETE_SUPPRESS_SPACE, Env:\_ARGCOMPLETE_IFS, Env:\_ARGCOMPLETE_SHELL
}