Skip to content

feat(mise): bootstrap WSL environment - #3702

Merged
risu729 merged 2 commits into
mainfrom
agent/migrate-to-mise-bootstrap
Jul 14, 2026
Merged

risu729 merged 2 commits into
mainfrom
agent/migrate-to-mise-bootstrap

Conversation

@risu729

@risu729 risu729 commented Jul 11, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • declare WSL system packages and home dotfiles in mise bootstrap configuration
  • replace imperative home linking and tool installation with mise bootstrap
  • keep privileged APT repository and /etc setup in the minimal WSL launcher
  • run remaining idempotent Docker, GnuPG, desktop database, Git config, and interactive auth setup as the final bootstrap task

Why

Mise now has first-class bootstrap packages and dotfile convergence. Using those facilities removes duplicated installer logic, adds status and dry-run support, and lets mise reload the newly installed global configuration before installing its tools.

.gitconfig remains a final task step because applying it in the dotfile phase would configure the gh credential helper before gh is installed.

Validation

  • mise fmt --check
  • mise task validate
  • shellcheck --external-sources wsl/install.sh
  • shfmt --diff --simplify wsl/install.sh
  • fresh temporary-home mise bootstrap --only dotfiles, followed by mise bootstrap dotfiles status --missing
  • staged-file pre-commit checks

The full local lint suite also passed all changed-file checks. Its unrelated Worker TypeScript tasks currently resolve worker/tsconfig.*.json from dir = "worker", resulting in nonexistent worker/worker/tsconfig.*.json paths. The WSL container integration test could not start locally because the CI-downloaded wsl-amd64.wsl artifact was absent; the PR CI job will download and exercise that image.

Summary by Sourcery

Use mise bootstrap as the primary WSL environment installer, delegating package, dotfile, and tool setup to mise while keeping the launcher minimal.

New Features:

  • Define WSL system packages and user dotfiles in mise bootstrap configuration, including apt packages and home directory mappings.
  • Add a dedicated bootstrap task to finish idempotent user setup (GnuPG dir, Docker group membership, desktop database update, Git config symlink, interactive Git/GitHub auth).

Enhancements:

  • Simplify the WSL install script to only handle system updates, privileged APT repo setup, and invoking mise bootstrap.
  • Configure mise to use symlink-based dotfiles by default, with explicit copy behavior for Codex skills and per-directory symlink modes.
  • Clarify README documentation to describe the WSL launcher, mise-based bootstrap, and broader role of root configuration files.

Documentation:

  • Update README to describe the WSL directory as a launcher plus mise bootstrap payload and to highlight that root configs now define machine bootstrap as well as the development toolchain.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @risu729, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
dotfiles-worker 4457db3 Jul 14 2026, 10:23 PM

@risu729
risu729 marked this pull request as ready for review July 14, 2026 22:39
@risu729
risu729 merged commit 9cc719c into main Jul 14, 2026
11 checks passed
@risu729
risu729 deleted the agent/migrate-to-mise-bootstrap branch July 14, 2026 22:39
@sourcery-ai

sourcery-ai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR refactors WSL bootstrap to delegate most user-space setup (APT packages, dotfiles, and mise tools) to mise bootstrap, leaving only privileged /etc and APT repo setup in the launcher, and adds a mise bootstrap task to finish idempotent WSL user configuration (GnuPG, Docker group, desktop DB, Git config, interactive Git/GPG setup).

File-Level Changes

Change Details Files
Replace imperative WSL user-space setup with mise bootstrap packages, dotfiles, and tools.
  • Remove manual installation of non-default system packages from the WSL launcher script.
  • Remove manual mise tool installation and home symlink management from the WSL launcher.
  • Add bootstrap.packages definitions for required apt packages in mise.toml.
  • Configure dotfile convergence in mise.toml via the [dotfiles] table and default symlink mode.
  • Update the launcher to call mise trust and mise bootstrap against the dotfiles repo.
wsl/install.sh
mise.toml
Move remaining idempotent user-level setup into a dedicated mise bootstrap task.
  • Add a bootstrap task in tasks.toml that initializes ~/.gnupg, updates the Docker group, refreshes the desktop database, and links .gitconfig.
  • Ensure .gitconfig is applied after tools and before interactive Git setup to avoid gh credential helper issues.
  • Run the interactive wsl/setup-git.ts script from the bootstrap task only in a fully interactive TTY.
tasks.toml
wsl/setup-git.ts
Keep privileged /etc and APT repository setup in the WSL launcher while narrowing its scope to mise installation.
  • Retain /etc/apt/keyrings and Docker APT repository configuration in the launcher script.
  • Change custom registry setup to only install mise via apt after setting repositories.
  • Continue to create /etc symlinks from wsl/etc in the launcher.
wsl/install.sh
Update documentation to reflect the new WSL bootstrap flow via mise.
  • Describe wsl/ as a WSL launcher plus files installed by mise bootstrap instead of a direct installer.
  • Clarify that root configuration files now define machine bootstrap in addition to tooling and checks.
README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • The new bootstrap task in tasks.toml assumes bash semantics (e.g., [[ ... ]]), but doesn’t set shell = "bash", which will cause failures if the default shell is /bin/sh; consider either declaring shell = "bash" for this task or rewriting the conditionals in POSIX [ ] form.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `bootstrap` task in `tasks.toml` assumes bash semantics (e.g., `[[ ... ]]`), but doesn’t set `shell = "bash"`, which will cause failures if the default shell is `/bin/sh`; consider either declaring `shell = "bash"` for this task or rewriting the conditionals in POSIX `[ ]` form.

## Individual Comments

### Comment 1
<location path="wsl/install.sh" line_range="210-211" />
<code_context>
-
-	run_git_setup_script "${dotfiles_dir}"
+	log_info "Bootstrapping packages, dotfiles, and tools with mise..."
+	mise trust --yes "${dotfiles_dir}/mise.toml"
+	mise --cd "${dotfiles_dir}" bootstrap --yes --update --force-dotfiles --locked
+	log_info "mise bootstrap completed."

</code_context>
<issue_to_address>
**issue (bug_risk):** The new `mise bootstrap` call does not invoke the bootstrap task you added in `tasks.toml`, so the post-setup steps are no longer executed.

Those post-setup actions were moved into the `[bootstrap]` task in `tasks.toml`, but `mise ... bootstrap` calls the built-in subcommand (using `mise.toml`), not that task. As a result, your new post-bootstrap steps won’t run. You likely want to invoke the task runner instead, e.g. `mise --cd "${dotfiles_dir}" run bootstrap`, or move all bootstrap behavior into `mise.toml` so there’s a single, correctly executed source of truth.
</issue_to_address>

### Comment 2
<location path="tasks.toml" line_range="17-26" />
<code_context>
 """
 description = "Run hk linters and formatters."

+[bootstrap]
+description = "Finish idempotent WSL user setup after packages, dotfiles, and tools are installed."
+run = '''
+mkdir --parents "${HOME}/.gnupg"
+chmod 700 "${HOME}/.gnupg"
+
+username=$(whoami)
+if ! groups "${username}" | grep --quiet --word-regexp docker; then
+  sudo usermod --append --groups docker "${username}"
+fi
+
+sudo update-desktop-database
+
+# Installing this before the tools phase makes Git use gh before gh is installed.
+ln --symbolic --no-dereference --force \
+  "${MISE_PROJECT_ROOT}/wsl/home/.gitconfig" "${HOME}/.gitconfig"
+
+if [[ -t 0 && -t 1 ]]; then
+  if ! bash --interactive -c "${MISE_PROJECT_ROOT}/wsl/setup-git.ts"; then
+    echo "Git setup failed; run wsl/setup-git.ts manually if needed." >&2
</code_context>
<issue_to_address>
**issue (bug_risk):** The bootstrap task script uses bash-specific features but does not specify `shell = "bash"`, which can break when run under the default shell.

This script uses bash-specific constructs (`[[ -t 0 && -t 1 ]]` and `bash --interactive -c ...`) but the task doesn’t set `shell` in `tasks.toml`, so it will run under mise’s default `/bin/sh`, where `[[ ... ]]` is invalid. Please either set `shell = "bash"` for this task or rewrite the conditionals to be POSIX-compliant (e.g., `test -t 0`, `test -t 1`, and `[ ]`).
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread wsl/install.sh
Comment on lines +210 to +211
mise trust --yes "${dotfiles_dir}/mise.toml"
mise --cd "${dotfiles_dir}" bootstrap --yes --update --force-dotfiles --locked

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): The new mise bootstrap call does not invoke the bootstrap task you added in tasks.toml, so the post-setup steps are no longer executed.

Those post-setup actions were moved into the [bootstrap] task in tasks.toml, but mise ... bootstrap calls the built-in subcommand (using mise.toml), not that task. As a result, your new post-bootstrap steps won’t run. You likely want to invoke the task runner instead, e.g. mise --cd "${dotfiles_dir}" run bootstrap, or move all bootstrap behavior into mise.toml so there’s a single, correctly executed source of truth.

Comment thread tasks.toml
Comment on lines +17 to +26
[bootstrap]
description = "Finish idempotent WSL user setup after packages, dotfiles, and tools are installed."
run = '''
mkdir --parents "${HOME}/.gnupg"
chmod 700 "${HOME}/.gnupg"

username=$(whoami)
if ! groups "${username}" | grep --quiet --word-regexp docker; then
sudo usermod --append --groups docker "${username}"
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): The bootstrap task script uses bash-specific features but does not specify shell = "bash", which can break when run under the default shell.

This script uses bash-specific constructs ([[ -t 0 && -t 1 ]] and bash --interactive -c ...) but the task doesn’t set shell in tasks.toml, so it will run under mise’s default /bin/sh, where [[ ... ]] is invalid. Please either set shell = "bash" for this task or rewrite the conditionals to be POSIX-compliant (e.g., test -t 0, test -t 1, and [ ]).

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.

1 participant