From 4df49338fea1cb1b76894de62c0a6b263c17dce7 Mon Sep 17 00:00:00 2001 From: Hugues Verlin Date: Thu, 19 Dec 2024 21:17:59 +0100 Subject: [PATCH] docs: update cookbook (#3718) --- docs/.vitepress/config.ts | 16 +- docs/mise-cookbook/cpp.md | 47 +++++ docs/mise-cookbook/docker.md | 59 ++++++ docs/mise-cookbook/index.md | 16 ++ docs/mise-cookbook/nodejs.md | 109 ++++++++++ docs/mise-cookbook/presets.md | 71 +++++++ docs/mise-cookbook/python.md | 46 ++++ docs/mise-cookbook/ruby.md | 36 ++++ docs/mise-cookbook/shell-tricks.md | 71 +++++++ .../terraform.md} | 6 +- docs/templates.md | 198 ++---------------- 11 files changed, 492 insertions(+), 183 deletions(-) create mode 100644 docs/mise-cookbook/cpp.md create mode 100644 docs/mise-cookbook/docker.md create mode 100644 docs/mise-cookbook/index.md create mode 100644 docs/mise-cookbook/nodejs.md create mode 100644 docs/mise-cookbook/presets.md create mode 100644 docs/mise-cookbook/python.md create mode 100644 docs/mise-cookbook/ruby.md create mode 100644 docs/mise-cookbook/shell-tricks.md rename docs/{mise-cookbook.md => mise-cookbook/terraform.md} (91%) diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 6d65078c9f..1fdbabdc4e 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -127,7 +127,21 @@ export default defineConfig({ { text: "FAQs", link: "/faq" }, { text: "Troubleshooting", link: "/troubleshooting" }, { text: "Tips & Tricks", link: "/tips-and-tricks" }, - { text: "Cookbook", link: "/mise-cookbook" }, + { + text: "Cookbook", + link: "/mise-cookbook", + collapsed: true, + items: [ + { text: "C++", link: "/mise-cookbook/cpp" }, + { text: "Docker", link: "/mise-cookbook/docker" }, + { text: "Node", link: "/mise-cookbook/nodejs" }, + { text: "Ruby", link: "/mise-cookbook/ruby" }, + { text: "Terraform", link: "/mise-cookbook/terraform" }, + { text: "Python", link: "/mise-cookbook/python" }, + { text: "Presets", link: "/mise-cookbook/presets" }, + { text: "Shell tricks", link: "/mise-cookbook/shell-tricks" }, + ], + }, { text: "Team", link: "/team" }, { text: "Roadmap", link: "/roadmap" }, { text: "Contributing", link: "/contributing" }, diff --git a/docs/mise-cookbook/cpp.md b/docs/mise-cookbook/cpp.md new file mode 100644 index 0000000000..367edae706 --- /dev/null +++ b/docs/mise-cookbook/cpp.md @@ -0,0 +1,47 @@ +# Mise + C++ Cookbook + +Here are some tips on managing C++ projects with mise. + +## A C++ Project with CMake + +```toml [mise.toml] +min_version = "2024.9.5" + +[env] +# Project information +PROJECT_NAME = "{{ config_root | basename }}" + +# Build directory +BUILD_DIR = "{{ config_root }}/build" + +[tools] +# Install CMake and make +cmake = "latest" +make = "latest" + +[tasks.configure] +description = "Configure the project" +run = "mkdir -p $BUILD_DIR && cd $BUILD_DIR && cmake .." + +[tasks.build] +description = "Build the project" +alias = "b" +run = "cd $BUILD_DIR && make" + +[tasks.clean] +description = "Clean the build directory" +alias = "c" +run = "rm -rf $BUILD_DIR" + +[tasks.run] +alias = "r" +description = "Run the application" +run = "$BUILD_DIR/bin/$PROJECT_NAME" + +[tasks.info] +description = "Print project information" +run = ''' +echo "Project: $PROJECT_NAME" +echo "Build Directory: $BUILD_DIR" +''' +``` diff --git a/docs/mise-cookbook/docker.md b/docs/mise-cookbook/docker.md new file mode 100644 index 0000000000..1d28f24f41 --- /dev/null +++ b/docs/mise-cookbook/docker.md @@ -0,0 +1,59 @@ +# Mise + Docker Cookbook + +Here are some tips on using Docker with mise. + +## Docker image with mise + +Here is an example Dockerfile showing how to install mise in a Docker image. + +```Dockerfile [Dockerfile] +FROM debian:12-slim + +RUN apt-get update \ + && apt-get -y --no-install-recommends install \ + # install any other dependencies you might need + sudo curl git ca-certificates build-essential \ + && rm -rf /var/lib/apt/lists/* + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +ENV MISE_DATA_DIR="/mise" +ENV MISE_CONFIG_DIR="/mise" +ENV MISE_CACHE_DIR="/mise/cache" +ENV MISE_INSTALL_PATH="/usr/local/bin/mise" +ENV PATH="/mise/shims:$PATH" +# ENV MISE_VERSION="..." + +RUN curl https://mise.run | sh +``` + +Build and run the Docker image: + +```shell +docker build -t debian-mise . +docker run -it --rm debian-mise +``` + +## Task to run mise in a Docker container + +This can be useful use if you need to reproduce an issue you're having with mise in a clean environment. + +```toml [mise.toml] +[tasks.docker] +run = "docker run --pull=always -it --rm --entrypoint bash jdxcode/mise:latest" +``` + +Example usage: + +```shell +❯ mise docker +[docker] $ docker run --pull=always -it --rm --entrypoint bash jdxcode/mise:latest +# latest: Pulling from jdxcode/mise +# Digest: sha256:eecc479b6259479ffca5a4f9c68dbfe8631ca62dc59aa60c9ab5e4f6e9982701 +# Status: Image is up to date for jdxcode/mise:latest +root@75f179a190a1:/mise# eval "$(mise activate bash)" +root@75f179a190a1:/mise# echo "" >/mise/config.toml +root@75f179a190a1:/mise# mise prune --yes +mise pruned configuration links +mise python@3.13.1 ✓ remove /mise/cache/python/3.13.1 +# ... +``` diff --git a/docs/mise-cookbook/index.md b/docs/mise-cookbook/index.md new file mode 100644 index 0000000000..8dfc78fac7 --- /dev/null +++ b/docs/mise-cookbook/index.md @@ -0,0 +1,16 @@ +# Cookbook + +Here we are sharing a few mise setups that other people have found useful. + +- [C++](cpp.md) +- [Docker](docker.md) +- [Node.JS](nodejs.md) +- [Python](python.md) +- [Ruby](ruby.md) +- [Terraform](terraform.md) + +Finally, here is how to create [presets](presets.md) and some [shell tricks](shell-tricks.md) you might find useful. + +## Contributing + +If you would like to share your setup, please share it in this [cookbook thread](https://github.com/jdx/mise/discussions/3645). diff --git a/docs/mise-cookbook/nodejs.md b/docs/mise-cookbook/nodejs.md new file mode 100644 index 0000000000..00355ef5b5 --- /dev/null +++ b/docs/mise-cookbook/nodejs.md @@ -0,0 +1,109 @@ +# Mise + Node.js Cookbook + +Here are some tips on managing Node.js projects with mise. + +## Add node modules binaries to the PATH + +A nice trick you can use is to add the node modules binaries to the PATH. This will make CLIs installed with npm available without `npx`. + +```toml [mise.toml] +[env] +_.path = ['./node_modules/.bin'] +``` + +Example: + +```shell +npm install --save eslint +eslint --version # works +``` + +## Example Node.js Project + +```toml [mise.toml] +min_version = "2024.9.5" + +[env] +_.path = ['{{config_root}}/node_modules/.bin'] + +# Use the project name derived from the current directory +PROJECT_NAME = "{{ config_root | basename }}" + +# Set up the path for node module binaries +BIN_PATH = "{{ config_root }}/node_modules/.bin" + +NODE_ENV = "{{ env.NODE_ENV | default(value='development') }}" + +[tools] +# Install Node.js using the specified version +node = "{{ env['NODE_VERSION'] | default(value='lts') }}" + +# Install some npm packages globally if needed +"npm:typescript" = "latest" +"npm:eslint" = "latest" +"npm:jest" = "latest" + +[tasks.install] +alias = "i" +description = "Install npm dependencies" +run = "npm install" + +[tasks.start] +alias = "s" +description = "Start the development server" +run = "npm run start" + +[tasks.lint] +alias = "l" +description = "Run ESLint" +run = "eslint src/" + +[tasks.test] +description = "Run tests" +alias = "t" +run = "jest" + +[tasks.build] +description = "Build the project" +alias = "b" +run = "npm run build" + +[tasks.info] +description = "Print project information" +run = ''' +echo "Project: $PROJECT_NAME" +echo "NODE_ENV: $NODE_ENV" +''' +``` + +## Example with `pnpm` + +This example uses `pnpm` as the package manager. This will skip installing dependencies if the lock file hasn't changed. + +```toml [mise.toml] +[tools] +node = '22' + +[hooks] +post_install = 'corepack enable' + +[env] +_.path = ['./node_modules/.bin'] + +[tasks.pnpmInstall] +description = 'Installs dependencies with pnpm' +run = 'pnpm install' +sources = ['package.json', 'pnpm-lock.yaml', 'mise.toml'] +outputs = ['node_modules/.pnpm/lock.yaml'] + +[tasks.dev] +description = 'Calls your dev script in `package.json`' +run = 'node --run dev' +depends = ['pnpmInstall'] +``` + +With this setup, getting started in a NodeJS project is as simple as running `mise dev`: + +- `mise` will install the correct version of NodeJS +- `mise` will enable `corepack` +- `pnpm install` will be run before `node --run dev` diff --git a/docs/mise-cookbook/presets.md b/docs/mise-cookbook/presets.md new file mode 100644 index 0000000000..86b57f7083 --- /dev/null +++ b/docs/mise-cookbook/presets.md @@ -0,0 +1,71 @@ +# Presets + +You can create your own presets by leveraging [mise tasks](../tasks/index.md) to reduce boilerplate and make it easier to set up new projects. + +## Example python preset + +Here is an example of how to create your python preset that creates a `mise.toml` file to work with `python` and `pdm` + +```shell [~/.config/mise/tasks/preset/python] +#!/usr/bin/env bash +#MISE dir="{{cwd}}" + +mise use pre-commit +mise config set env._.python.venv.path .venv +mise config set env._.python.venv.create true -t bool +mise tasks add lint -- pre-commit run -a +``` + +```shell [~/.config/mise/tasks/preset/pdm] +#!/usr/bin/env bash +#MISE dir="{{cwd}}" +#MISE depends=["preset:python"] +#USAGE arg "" + +mise use python@$usage_version +mise use pdm@latest +mise config set hooks.postinstall "pdm sync" +``` + +Then in any directory, you can run `mise preset:pdm 3.10` to scaffold a new project with `python` and `pdm`: + +```shell +cd my-project +mise preset:pdm 3.10 +# [preset:python] $ ~/.config/mise/tasks/preset/python +# mise WARN No untrusted config files found. +# mise ~/my-project/mise.toml tools: pre-commit@4.0.1 +# [preset:pdm] $ ~/.config/mise/tasks/preset/pdm 3.10 +# mise WARN No untrusted config files found. +# mise ~/my-project/mise.toml tools: python@3.10.15 +# mise ~/my-project/mise.toml tools: pdm@2.21.0 +# mise creating venv with uv at: ~/my-project/.venv +# Using CPython 3.10.15 interpreter at: /Users/simon/.local/share/mise/installs/python/3.10.15/bin/python +# Creating virtual environment at: .venv +# Activate with: source .venv/bin/activate.fish + +~/my-project via 🐍 v3.10.15 (.venv) +# we are in the virtual environment ^ +``` + +Here is the generated `mise.toml` file: + +```toml [mise.toml] +[tools] +pdm = "latest" +pre-commit = "latest" +python = "3.10" + +[hooks] +postinstall = "pdm sync" + +[env] +[env._] +[env._.python] +[env._.python.venv] +path = ".venv" +create = true + +[tasks.lint] +run = "pre-commit run -a" +``` diff --git a/docs/mise-cookbook/python.md b/docs/mise-cookbook/python.md new file mode 100644 index 0000000000..2a8938b912 --- /dev/null +++ b/docs/mise-cookbook/python.md @@ -0,0 +1,46 @@ +# Mise + Python Cookbook + +Here are some tips on managing Python projects with mise. + +## A Python Project with virtualenv + +Here is an example python project with a `requirements.txt` file. + +```toml [mise.toml] +min_version = "2024.9.5" + +[env] +# Use the project name derived from the current directory +PROJECT_NAME = "{{ config_root | basename }}" + +# Automatic virtualenv activation +_.python.venv = { path = ".venv", create = true } + +[tools] +python = "{{ get_env(name='PYTHON_VERSION', default='3.11') }}" +ruff = "latest" + +[tasks.install] +description = "Install dependencies" +alias = "i" +run = "uv pip install -r requirements.txt" + +[tasks.run] +description = "Run the application" +run = "python app.py" + +[tasks.test] +description = "Run tests" +run = "pytest tests/" + +[tasks.lint] +description = "Lint the code" +run = "ruff src/" + +[tasks.info] +description = "Print project information" +run = ''' +echo "Project: $PROJECT_NAME" +echo "Virtual Environment: $VIRTUAL_ENV" +''' +``` diff --git a/docs/mise-cookbook/ruby.md b/docs/mise-cookbook/ruby.md new file mode 100644 index 0000000000..c9adcb9102 --- /dev/null +++ b/docs/mise-cookbook/ruby.md @@ -0,0 +1,36 @@ +# Mise + Ruby Cookbook + +Here are some tips on managing Ruby projects with mise. + +## A Ruby on Rails Project + +```toml [mise.toml] +min_version = "2024.9.5" + +[env] +# Project information +PROJECT_NAME = "{{ config_root | basename }}" + +[tools] +# Install Ruby with the specified version +ruby = "{{ get_env(name='RUBY_VERSION', default='3.3.3') }}" + +[tasks."bundle:install"] +description = "Install gem dependencies" +run = "bundle install" + +[tasks.server] +description = "Start the Rails server" +alias = "s" +run = "rails server" + +[tasks.test] +description = "Run tests" +alias = "t" +run = "rails test" + +[tasks.lint] +description = "Run lint using Rubocop" +alias = "l" +run = "rubocop" +``` diff --git a/docs/mise-cookbook/shell-tricks.md b/docs/mise-cookbook/shell-tricks.md new file mode 100644 index 0000000000..1fcf165800 --- /dev/null +++ b/docs/mise-cookbook/shell-tricks.md @@ -0,0 +1,71 @@ +# Shell tricks + +A collection of shell utities leveraging mise. + +## Prompt colouring + +In ZSH to set the prompt colour whenever mise updates the environment (e.g. on cd into a project, or due to modification of the .mise\*.toml): + +```shell +# activate mise like normal +source <(command mise activate zsh) + +typeset -i _mise_updated + +# replace default mise hook +function _mise_hook { + local diff=${__MISE_DIFF} + source <(command mise hook-env -s zsh) + [[ ${diff} == ${__MISE_DIFF} ]] + _mise_updated=$? +} + +_PROMPT="❱ " # or _PROMPT=${PROMPT} to keep the default + +function _prompt { + if (( ${_mise_updated} )); then + PROMPT='%F{blue}${_PROMPT}%f' + else + PROMPT='%(?.%F{green}${_PROMPT}%f.%F{red}${_PROMPT}%f)' + fi +} + +add-zsh-hook precmd _prompt +``` + +Now, when mise makes any updates to the environment the prompt will go blue. + +## Inspect what changed after mise hook + +Using record-query you can inspect the `__MISE_DIFF` and `__MISE_SESSION` variables to see what's changing in your environment due to the mise hook. + +```toml [~/.config/mise/config.toml] +[tools] +"cargo:record-query" = "latest" +``` + +```shell +function mise_parse_env { + rq -m < <( + zcat -q < <( + printf $'\x1f\x8b\x08\x00\x00\x00\x00\x00' + base64 -d <<< "$1" + ) + ) +} +``` + +```shell +$ mise_parse_env "${__MISE_DIFF}" +{ + "new": { + ... + }, + "old": { + ... + }, + "path": [ + ... + ] +} +``` diff --git a/docs/mise-cookbook.md b/docs/mise-cookbook/terraform.md similarity index 91% rename from docs/mise-cookbook.md rename to docs/mise-cookbook/terraform.md index 28faca21b4..c429624958 100644 --- a/docs/mise-cookbook.md +++ b/docs/mise-cookbook/terraform.md @@ -1,6 +1,6 @@ -# Tasks Cookbook +# Mise + Terraform/Opentofu Cookbook -Here we are sharing a few configurations for tasks that other people have found useful. +Here are some tips on managing Terraform projects with mise. ## Managing `terraform`/`opentofu` Projects @@ -9,7 +9,7 @@ This necessitates the use of syntax like `terraform -chdir=terraform plan` to us terraform command. The following config allows you to invoke all of them from `mise`, leveraging `mise` tasks. -```toml +```toml [mise.toml] [tools] terraform = "1" diff --git a/docs/templates.md b/docs/templates.md index 79f09bc7d0..767b123391 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -2,6 +2,10 @@ Templates in mise provide a powerful way to configure different aspects of your environment and project settings. + +A template is a string that contains variables, expressions, and control structures. +When rendered, the template engine (`tera`) replaces the variables with their values. + You can define and use templates in the following locations: - Most `mise.toml` configuration values @@ -9,6 +13,20 @@ You can define and use templates in the following locations: - `.tool-versions` files - _(Submit a ticket if you want to see it used elsewhere!)_ +## Example + +Here is an example of a `mise.toml` file that uses templates: + +```toml +[env] +PROJECT_NAME = "{{ cwd | basename }}" + +[tools] +node = "{{ get_env(name='NODE_VERSION', default='20') }}" +``` + +You will find more examples in the [cookbook](./mise-cookbook/index.md). + ## Template Rendering Mise uses [tera](https://keats.github.io/tera/docs/) to provide the template feature. @@ -213,7 +231,7 @@ Some filters: - `str | date(format) -> String` – Converts a timestamp to a formatted date string using the provided format, such as `{{ ts | date(format="%Y-%m-%d") }}`. - Find a list of time format on [`chrono` documentation][chrono-doc]. + Find a list of time format on [`chrono` documentation](https://docs.rs/chrono/latest/chrono/format/strftime/index.html). - `str | split(pat) -> Array` – Splits a string by the given pattern and returns an array of substrings. - `str | default(value) -> String` – Returns the default value @@ -289,181 +307,3 @@ Mise offers additional tests: - `if path is dir` – Checks if the provided path is a directory. - `if path is file` – Checks if the path points to a file. - `if path is exists` – Checks if the path exists. - -### Example Templates - -#### A Node.js Project - -```toml -min_version = "2024.9.5" - -[env] -# Use the project name derived from the current directory -PROJECT_NAME = "{{ cwd | basename }}" - -# Set up the path for node module binaries -BIN_PATH = "{{ cwd }}/node_modules/.bin" - -NODE_ENV = "{{ env.NODE_ENV | default(value='development') }}" - -[tools] -# Install Node.js using the specified version -node = "{{ env['NODE_VERSION'] | default(value='lts') }}" - -# Install npm packages globally if needed -"npm:typescript" = "latest" -"npm:eslint" = "latest" -"npm:jest" = "latest" - -# Install npm dependencies -[tasks.install] -alias = "i" -run = "npm install" - -# Run the development server -[tasks.start] -alias = "s" -run = "npm run start" - -# Run linting -[tasks.lint] -alias = "l" -run = "eslint src/" - -# Run tests -[tasks.test] -alias = "t" -run = "jest" - -# Build the project -[tasks.build] -alias = "b" -run = "npm run build" - -# Print project info -[tasks.info] -run = ''' -echo "Project: $PROJECT_NAME" -echo "NODE_ENV: $NODE_ENV" -''' -``` - -#### A Python Project with virtualenv - -```toml -min_version = "2024.9.5" - -[env] -# Use the project name derived from the current directory -PROJECT_NAME = "{{ cwd | basename }}" - -# Automatic virtualenv activation -_.python.venv = { path = ".venv", create = true } - -[tools] -# Install the specified Python version -python = "{{ get_env(name='PYTHON_VERSION', default='3.11') }}" - -# Install dependencies -[tasks.install] -alias = "i" -run = "pip install -r requirements.txt" - -# Run the application -[tasks.run] -run = "python app.py" - -# Run tests -[tasks.test] -run = "pytest tests/" - -# Lint the code -[tasks.lint] -run = "ruff src/" - -# Print environment information -[tasks.info] -run = ''' -echo "Project: $PROJECT_NAME" -echo "Virtual Environment: $VIRTUAL_ENV" -''' -``` - -#### A C++ Project with CMake - -```toml -min_version = "2024.9.5" - -[env] -# Project information -PROJECT_NAME = "{{ cwd | basename }}" - -# Build directory -BUILD_DIR = "{{ cwd }}/build" - -[tools] -# Install CMake and make -cmake = "latest" -make = "latest" - -# Configure the project -[tasks.configure] -run = "mkdir -p $BUILD_DIR && cd $BUILD_DIR && cmake .." - -# Build the project -[tasks.build] -alias = "b" -run = "cd $BUILD_DIR && make" - -# Clean the build directory -[tasks.clean] -alias = "c" -run = "rm -rf $BUILD_DIR" - -# Run the application -[tasks.run] -alias = "r" -run = "$BUILD_DIR/bin/$PROJECT_NAME" - -# Print project info -[tasks.info] -run = ''' -echo "Project: $PROJECT_NAME" -echo "Build Directory: $BUILD_DIR" -''' -``` - -#### A Ruby on Rails Project - -```toml -min_version = "2024.9.5" - -[env] -# Project information -PROJECT_NAME = "{{ cwd | basename }}" - -[tools] -# Install Ruby with the specified version -ruby = "{{ get_env(name='RUBY_VERSION', default='3.3.3') }}" - -# Install gem dependencies -[tasks."bundle:install"] -run = "bundle install" - -# Run the Rails server -[tasks.server] -alias = "s" -run = "rails server" - -# Run tests -[tasks.test] -alias = "t" -run = "rails test" - -# Lint the code -[tasks.lint] -alias = "l" -run = "rubocop" -``` - -[chrono-doc]: https://docs.rs/chrono/0.4.38/chrono/format/strftime/index.html