Skip to content

Conversation

@MrPointer
Copy link
Owner

Summary

This PR is HUGE, but probably the most important one that ever was here.
In short, it's a refactor to the initial bootstrapper, which I also call "installer", to become a single binary that can run on every supported platform.
Instead of being written in Bash, resulting in something hard to maintain and especially test, it's written in Go. Combined with a testable archtecture it results in a very stable binary that's also much easier to maintain over time. The same capabilities are kept so far.

This also makes it possible to use GitHub's CI to verify the installer works for all supported platforms and doesn't break as I keep making changes.

@MrPointer MrPointer self-assigned this Oct 14, 2025
@MrPointer MrPointer marked this pull request as draft October 17, 2025 18:01
@MrPointer MrPointer force-pushed the feature/go-installer branch 3 times, most recently from 5819ad0 to f9c7fe2 Compare October 21, 2025 13:22
This will serve as the base for my next-gen installer.
Changing the config file is much easier than changing code,
and by embedding it, we allow a "batteries included" experience.
The goal is to ensure that the dotfiles are compatible with
the os-distribution and later also the version of the OS.
This is the first step of the dotfiles installation process, and is
done mostly to avoid any unexpected behavior.
Currently it only checks compatibility by invoking the existing
`check-compatibility` command.
There are valuable logs across internal library functions
that can be used to debug issues, but they should not be
logged unless the user has explicitly enabled logging.
For cli commands, logging is enabled by default.
We already collect all this info when checking for OS compatibility,
so we can return a struct with all the info we need for other
components to use.
This is the first step of the install command.
It will check if brew is installed and if not, it will install it.
It's the same functionality from the shell script, ported to go.
Also improved the error handling of the brew package,
and added some debug logs.
The output template is still matryer's moq as I like it better than
testify's mocks.
It includes building the installer binary, running all tests, and trying
to check all its commands, namely `install`, are working for all
environments we care about.
We'll get back to them eventually when they'll be of better use, at
least some of them.
The tests tried to directly access the same buffer used by the
underlying `huh` library for showing the progress without any guards in
place, because `bytes.Buffer` isn't thread safe, and that caused Go's
race detector to report races. By implemeneting a safe buffer (and
writer), and reading from it safely in the tests themselves, the problem
is mitigated.
These fail in CI, but were finally run as I'm on a Mac and couldn't run
them, at least without a container.
Our binary doesn't have a `--version` option, it's not needed.
We don't need to setup any Linux dependencies as those should be
installed by our binary, and it's actually part of the test. For mac,
however, it lacks the `timeout` command called by the CI job, hence we
need to install coreutils first.
It should pass if it just reports prequisites as missing, because this
is expected and considered normal behavior.
It automates GPG input when creating a new key, assuming no keys exist
to select from.
@MrPointer MrPointer force-pushed the feature/go-installer branch from f9c7fe2 to 29cf3e2 Compare November 21, 2025 12:39
It's done using the recently added expect automation.
@MrPointer MrPointer force-pushed the feature/go-installer branch from 29cf3e2 to 930310f Compare November 21, 2025 13:18
Trying to selectively filter which tests are OK to fail based on the
failure reason is brittle and already proved itself wrong, where tests
failing on macos due to a real bug in the installer were marked as
successful, giving the false illusion that everything is working
correctly.
@MrPointer MrPointer force-pushed the feature/go-installer branch 2 times, most recently from 02d68fe to ae2502d Compare November 21, 2025 16:14
The installer created the data directory using Go's user home dir, but
apparently chezmoi expects a specific home instead, even on Mac, which
makes sense because that's where dotfiles usually live. To not
breakother callers that may use Go's home dir, an additional method to
get the chezmoi-specific dir has been added, and tests have been updated
to use correct mocks.
I always want to be able to run tests, even if nothing has changed.
@MrPointer MrPointer force-pushed the feature/go-installer branch from 8505f8c to 6b497a2 Compare November 21, 2025 22:04
It's mandatory to account for weird differnces between platforms.
@MrPointer MrPointer force-pushed the feature/go-installer branch from dfe1e7b to 4b5fd2d Compare November 21, 2025 23:09
@MrPointer MrPointer marked this pull request as ready for review November 22, 2025 14:41
@MrPointer MrPointer merged commit ddf73d8 into main Nov 22, 2025
5 checks passed
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.

2 participants