Skip to content

feat: distrobox v2.0#2122

Open
dottorblaster wants to merge 137 commits into
mainfrom
next
Open

feat: distrobox v2.0#2122
dottorblaster wants to merge 137 commits into
mainfrom
next

Conversation

@dottorblaster

Copy link
Copy Markdown
Collaborator

No squash-merge for this! We are just merging all the v2.0 efforts in main.

More about that at: https://distrobox.it/posts/announcing_distrobox_next/

fabriziosestito and others added 4 commits June 11, 2026 18:24
Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>
* build(deps): add urfave/cli

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* chore: add gitignore

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* ci: add golangci configuration

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* build(Makefile): add Makefile

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* feat: add main package and distrobox cmd

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

---------

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>
* feat: add containermanager package and docker provider

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* feat: add list command

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* feat: add root command

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* feat: add list command

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* feat: wire-up root command in main

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* refactor(docker): use format json

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

---------

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>
Comment thread .github/workflows/compatibility.yml Outdated
@dottorblaster dottorblaster force-pushed the next branch 2 times, most recently from 56c15d2 to 21e6b9a Compare June 14, 2026 10:55
balanza and others added 12 commits June 14, 2026 12:57
* chore: disable mdlint (#6)

* resolve lint issues

Some issues where detected by the CI once run:
* use of `fmt.Printf` forbidden by pattern `^(fmt\.Print(|f|ln)|print|println)$` (forbidigo)
* File is not properly formatted (goimports)
* Magic number: 12, in <condition> detected (mnd)
* error-format: fmt.Errorf can be replaced with errors.New (perfsprint)

---------

Co-authored-by: Alessio Biancalana <alessio@dottorblaster.it>
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](actions/checkout@v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
* feat(cli): validate sudo (sudo -v) in beforeCommand if --root is set

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* feat(docker): add root and sudoCommand and execute commands with sudo if root is set

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* feat(cli): add --root description and -r alias

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

---------

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>
* add GenerateEntryCommand package

The package mimics the actual distrobox-generate-entry shell command
that installs a desktop entry file so that the host's desktop
environment can render the appropriate application icon.
This first implementantion scaffolds the command package and implements
the simplest scenario for a single container.

* delete entry

If the `delete` flag is provided, the command remove the desktop entry
if present.
Deleting a non-existing item does not raise an error.

* generate entries for all containers

With `opts.All` we implement an abstraction over the
`GenerateEntryCommand` that iterates across all the containers to
generate or delete the relative desktop entries.
`ListCommand` is used to fetch the list of containers.

* mount the generate-entry cli command

Mount the command so that is reachable from the CLI. Define parameters
with type and basic validation.
Depending on the flag `--all`, the appropriate set of options is provided
to the `GenerateEntryCommand.Execute()` method.
If `--all` is set, `container-name` and `icon` arguments will be ignored.
* embed shell scripts to execute inside the distrobox

The command init, export and host-exec must be accessible from inside
the distrobox container.
When needed, the embedded scripts will be written to a host directory
and then mounted as volume on the created container.
The host directory is determined by configuration and environment
variables.
The script will be not converted to GO to keep then
architecture-agnostic.

* add Create to the Docker container manager

The function will compose argument string to append to the `docker`
command.
If `DryRun=true`, the command is just printed on screen and not
executed.

* add Create command package

* mount cli command
* feat: add config

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* build(deps): add testify

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

* test(config): add config loading test

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>

---------

Signed-off-by: Fabrizio Sestito <fabrizio.sestito@suse.com>
* feat(enter): rewrite in go

* chore: make InspectContainer public

* chore: use userenv package for user's environment

* chore: export InspectResult type for convenience

* fix: rename containerInspect to inpectOutput

* fix: use userenv inside generateEnterCommand

* fix(enter): more userenv

* chore: add some unit tests for buildContainerPath and buildCommandArgs
@dottorblaster dottorblaster force-pushed the next branch 2 times, most recently from 915611a to 2db8252 Compare June 14, 2026 11:01
balanza added 2 commits June 14, 2026 13:04
* read desktop entry directory and distrobox path from the global config

* implement entry generation requested from user
* remove unused ID field

* add a test for include order
89luca89 and others added 28 commits June 14, 2026 13:04
Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
Some flags are shared to many commands but not to all (example: `--root`). By composing decorators, each command can be configured so that is assigned only to the flags that matters.
`assemble` command cannot be executed as root. Instead, each item can
either be processed by a rootful or rootless container manager.
Previously, the CLI hardcoded "1.0.0" as the version string in two places (the root command and the generate-entry subcommand).

Introduce pkg/version, a minimal package that exposes a single variable Version, defaulting to "dev". The root command now references such a value; generate-entry does not need it al all

The Makefile computes the version at build time by running:

git describe --tags --always
This produces the exact tag name when HEAD is tagged, or --g when it is not, giving a precise description of the build relative to the nearest ancestor tag. If git is unavailable, the value falls back to "dev".

The resulting string is injected into the binary via:

-ldflags "-X github.com/89luca89/distrobox/pkg/version.Version=<value>" so that distrobox --version and distrobox generate-entry --version both report the exact version of the build.
`Interactive: !NoTTY` routed stdio to discarded buffers whenever
--no-tty was set, breaking ptyxis. --no-tty only governs whether
`--tty` is appended to the exec args, not stdio plumbing.

Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
Wire signal.NotifyContext in main so SIGINT/SIGTERM cancel the context
instead of killing the process.

ephemeral and assemble now defer rm on a detached cleanup ctx, so the
in-flight container is removed even when the user hits Ctrl+C.

Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
PullImage ignored opts.DryRun and pulled anyway.
Thread DryRun through PullImage and gate
the usesRunc / supportsKeepIDSize probes.

Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
`makeContainerName` replaced user-provided names with DefaultContainerName
whenever `image=` was empty, and `sectionToItem` kept whitespace from
headers like `[ generic1]`.
Both made `assemble create` emit `--name my-distrobox` (or a leading-space name)
for sections without an explicit image.

Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
- enter: fall back to cfg.DefaultContainerName (was passing "" to the manager)
- rm: fall back to cfg.DefaultContainerName (was a silent no-op)
- upgrade: error with "Please specify the name of the container." (was silently using my-distrobox)

Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
* chore(ci): update actions and pin them to commit sha

* chore(dependabot): add gomod package ecosystem

* chore(dependabot): add cooldown for package updates
Forward the command/arguments collected after `--` on the ephemeral CLI
through `EphemeralOptions.CustomCommand` to the underlying enter
command, matching the bash reference (`distrobox-enter ... ${name}
${container_command}`). Without this, examples like `distrobox
ephemeral --image alpine -- cat /etc/os-release` would silently drop
the trailing command and just open an interactive shell.
…r name (#2108)

Generate the random ephemeral container name in a loop that re-rolls if
the name already exists according to the container manager, and fail
loudly after a small number of attempts. Dry-run mode bypasses the
existence check to match the rest of the dry-run pipeline.

Also extends MockContainerManager with an optional ExistsFn override so
tests can simulate collisions without changing behavior for existing
tests (the default still returns false).
`distrobox assemble create /path/to/file.ini` and
`distrobox assemble rm /path/to/file.ini` now work the same way as the
original Bash `distrobox-assemble` script, in addition to the existing
`--file` flag. When both are supplied, `--file` takes precedence
(explicit over implicit). When neither is given, the default
`./distrobox.ini` is still used.

The resolution logic is extracted into a `resolveManifestPath` helper
with unit tests covering flag precedence, positional fallback and the
default path.
When `--icon auto` is used (the implicit default for `--all`),
match the container's image name (or container name as fallback)
against the upstream DISTRO_ICON_MAP and select the matching distro
logo. Falls back to the generic terminal icon when no distro can be
detected, preserving previous behaviour.
When `--additional-flags --label=manager=...` overrides the manager
label at creation time, `distrobox list` would hide the container and
`distrobox rm` would silently no-op (it filters through the same list).
Match the distrobox.* label set alongside `manager` so containers
remain detectable when the manager label is overridden, restoring v1's
loose `*distrobox*` substring behavior.
The DE (at least Gnome and KDE) tries to match the app_id of
the running application with the corresponding .desktop file in this order:
 - find ${app_id}.desktop
 - if not found, tries to find a .desktop with StartupWMClass=${app_id}
Because when exporting a application we change the name of the .desktop
file, the DE can't match the running app, displaying a generic icon.

To solve this, change StartupWMClass key of the exported .desktop file
to the name of the .desktop inside distrobox (minus the .desktop extension).
Ports show_compatibility from bash distrobox-create. Downloads
docs/compatibility.md from upstream and caches the parsed list
in the user cache dir.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants