mooncake

module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 30, 2026 License: MIT

README

Mooncake build

Space fighters provisioning tool, Chookity!

Installation

go install github.com/alehatsman/mooncake@latest

Usage

Mooncake features an animated TUI (Text User Interface) by default that shows real-time progress with an animated character. Use --raw to disable the animation.

# Run configuration
mooncake run --config config.yml

# With variables file
mooncake run --config config.yml --vars vars.yml

# With sudo password
mooncake run --config config.yml --sudo-pass <password>

# Filter by tags
mooncake run --config config.yml --tags dev
mooncake run --config config.yml --tags dev,prod,test

# Preview what would be executed (dry-run)
mooncake run --config config.yml --dry-run

# Disable animated UI (use raw console output)
mooncake run --config config.yml --raw

# With debug logging
mooncake run --config config.yml --log-level debug
CLI Flags
  • --config, -c: Path to configuration file (required)
  • --vars, -v: Path to variables file
  • --log-level, -l: Log level - debug, info, or error (default: info)
  • --sudo-pass, -s: Sudo password for steps with become: true
  • --tags, -t: Filter steps by tags (comma-separated)
  • --dry-run: Preview what would be executed without making any changes (validates and shows preview)
  • --raw, -r: Disable animated TUI and use raw console output

Features

  • Execute shell commands with templating
  • Create files and directories with configurable permissions
  • Render templates using pongo2
  • Conditional execution with expressions
  • Include other configuration files
  • Load variables from external files
  • File tree iteration with with_filetree
  • List iteration with with_items
  • Relative path resolution
  • Global system facts (os, arch)
  • Animated TUI with live progress tracking
  • Dry-run mode for safe preview and validation

Dry-Run Mode

Preview what would be executed and validate your configuration without making any changes to your system:

mooncake run --config config.yml --dry-run

What it does:

  • Validates YAML syntax and step structure
  • Checks that required files exist (template sources, included configs, variable files)
  • Verifies paths can be expanded and variables resolved
  • Shows commands that would be executed
  • Shows files and directories that would be created
  • Shows templates that would be rendered
  • Shows variables that would be set
  • Processes includes recursively to show all steps

Example output:

[1/3] Create directory
  [DRY-RUN] Would create directory: /home/user/.config (mode: 0755)
[2/3] Render config
  [DRY-RUN] Would template: ./template.j2 -> /home/user/.config/app.conf (mode: 0644)
[3/3] Run setup
  [DRY-RUN] Would execute: apt install neovim
  [DRY-RUN] With sudo privileges

Use cases:

  • Test and validate configurations before applying them
  • Preview changes in production environments
  • Debug complex configurations with conditionals and includes
  • Verify variable substitution and template rendering
  • Check that all required files exist

File Structure

YAML Format

Configuration files are YAML arrays of steps. Each step must have exactly one action:

- name: First step
  shell: echo "hello"

- name: Second step
  file:
    path: /tmp/test
    state: directory
Path Resolution

Mooncake uses Node.js-like relative path resolution. All relative paths are resolved relative to the current configuration file, not the working directory.

project/
├── main.yml
├── configs/
│   ├── neovim.yml
│   └── templates/
│       └── init.lua.j2
└── dotfiles/
    └── .bashrc

main.yml:

- name: Include neovim config
  include: ./configs/neovim.yml  # Relative to main.yml

configs/neovim.yml:

- name: Render init.lua
  template:
    src: ./templates/init.lua.j2  # Relative to neovim.yml
    dest: ~/.config/nvim/init.lua
Organizing Configurations

You can organize your configuration in multiple ways:

Flat structure:

provisioning/
├── main.yml
├── linux.yml
├── macos.yml
└── common.yml

Nested structure:

provisioning/
├── main.yml
├── os/
│   ├── linux.yml
│   └── macos.yml
├── apps/
│   ├── neovim.yml
│   ├── tmux.yml
│   └── zsh.yml
└── templates/
    ├── init.lua.j2
    ├── tmux.conf.j2
    └── zshrc.j2

main.yml:

- vars:
    config_dir: ~/.config

- name: Load OS-specific configuration
  include: ./os/linux.yml
  when: os == "linux"

- name: Load OS-specific configuration
  include: ./os/macos.yml
  when: os == "darwin"

- name: Setup neovim
  include: ./apps/neovim.yml

- name: Setup tmux
  include: ./apps/tmux.yml
Path Types

Relative paths (start with ./ or ../):

include: ./configs/app.yml
src: ../templates/config.j2

Absolute paths:

dest: /etc/nginx/nginx.conf
path: /var/log/app

Home directory paths (use ~ or template filter):

dest: ~/.config/nvim/init.lua
dest: "{{ '~/.config' | expanduser }}/nvim/init.lua"

Configuration

Variables

Define and use variables throughout your configuration:

- vars:
    config_dir: ~/.config
    nvim_dir: "{{config_dir}}/nvim"

- name: Create nvim directory
  file:
    path: "{{nvim_dir}}"
    state: directory
Include Variables

Load variables from external YAML files:

- name: Load environment variables
  include_vars: ./env.yml
Global Variables

Available in all steps:

  • os: linux | darwin | windows
  • arch: amd64 | arm64 | etc
File

Create files or directories with optional permissions:

- name: Create directory
  file:
    path: ~/.config/nvim
    state: directory
    mode: "0755"

- name: Create empty file
  file:
    path: ~/.config/nvim/init.lua
    state: file
    mode: "0644"

- name: Create file with content
  file:
    path: /tmp/test.txt
    state: file
    content: "Hello World"
Template

Render templates using pongo2 syntax:

- name: Render config file
  template:
    src: ./init.lua.j2
    dest: ~/.config/nvim/init.lua
    mode: "0644"
    vars:
      port: 8080
      debug: true

Template supports pongo2 features:

# Variables
{{ variable_name }}

# Conditionals
{% if debug %}
debug_mode = true
{% endif %}

# Loops
{% for item in items %}
- {{ item }}
{% endfor %}

# Filters
{{ path|expanduser }}  # Expands ~ to home directory
{{ text|upper }}
Shell

Execute shell commands:

- name: Install packages
  shell: brew install neovim ripgrep

- name: Run multiple commands
  shell: |
    echo "Starting setup"
    mkdir -p ~/.local/bin
    echo "Setup complete"
Include

Include other configuration files:

- name: Include Linux configuration
  include: ./linux.yml

- name: Include with relative path
  include: ./configs/neovim.yml
Conditional Execution

Use when to conditionally execute steps:

- name: Install Linux packages
  shell: apt install neovim
  when: os == "linux"

- name: Install macOS packages
  shell: brew install neovim
  when: os == "darwin"

- name: Complex condition
  shell: echo "ARM Mac"
  when: os == "darwin" && arch == "arm64"

Supported operators:

  • Comparison: ==, !=, >, <, >=, <=
  • Logical: &&, ||, !
  • Arithmetic: +, -, *, /, %
File Tree Iteration

Iterate over files in a directory:

- name: Copy dotfiles
  template:
    src: "{{ item.src }}"
    dest: "~/.config/{{ item.name }}"
  with_filetree: ./dotfiles

Each iteration provides:

  • item.src: Source file path
  • item.name: File name
  • item.is_dir: Boolean indicating if item is directory
List Iteration

Iterate over a list of items using with_items:

- vars:
    packages:
      - neovim
      - ripgrep
      - tmux
      - fzf

- name: Install packages
  shell: brew install {{ item }}
  with_items: "{{ packages }}"

You can also iterate over inline lists:

- vars:
    users:
      - alice
      - bob
      - charlie

- name: Create user directories
  file:
    path: "/home/{{ item }}"
    state: directory
    mode: "0755"
  with_items: "{{ users }}"

Each iteration provides the current item in the item variable

Tags

Filter execution by tags. When tags filter is specified, only steps with matching tags are executed:

- name: Step without tags
  shell: echo "Always runs when no filter specified"

- name: Install development tools
  shell: brew install neovim ripgrep
  tags:
    - dev
    - tools

- name: Setup production
  shell: setup-production.sh
  tags:
    - prod

- name: Deploy to staging
  shell: deploy-staging.sh
  tags:
    - deploy
    - staging

Behavior:

  • No tags filter: All steps execute (including untagged steps)
  • With tags filter: Only steps with matching tags execute; untagged steps are skipped
  • Multiple tags: Step executes if it has ANY of the specified tags

Run with tags:

# Run only dev-tagged steps
mooncake run --config config.yml --tags dev

# Run dev OR prod tagged steps
mooncake run --config config.yml --tags dev,prod

# Run steps tagged with deploy OR staging
mooncake run --config config.yml --tags deploy,staging
Sudo/Become

Execute commands with sudo:

- name: Install system package
  shell: apt install neovim
  become: true

Provide sudo password:

mooncake run --config config.yml --sudo-pass <password>

Note: Only steps with become: true will use sudo.

File Permissions

Specify file permissions in octal format:

- name: Create executable script
  file:
    path: ~/.local/bin/script.sh
    state: file
    content: "#!/bin/bash\necho hello"
    mode: "0755"

- name: Create private config
  template:
    src: ./secret.yml.j2
    dest: ~/.config/secret.yml
    mode: "0600"

Examples

See the examples/ directory for complete working examples:

  • Basic examples: Hello world, files, conditionals, tags
  • Advanced examples: Multi-file configurations, includes, variables

Example Configuration

- vars:
    config_dir: ~/.config
    nvim_dir: "{{config_dir}}/nvim"
    nvim_config: "{{nvim_dir}}/init.lua"

- name: Ensure neovim config directory exists
  file:
    path: "{{nvim_dir}}"
    state: directory
    mode: "0755"

- name: Render neovim configuration
  template:
    src: ./init.lua.j2
    dest: "{{nvim_config}}"
    mode: "0644"

- name: Install neovim on macOS
  shell: brew install neovim
  when: os == "darwin"

- name: Install neovim on Linux
  shell: apt install neovim
  become: true
  when: os == "linux"

- name: Copy plugin configs
  template:
    src: "{{item.src}}"
    dest: "{{nvim_dir}}/lua/{{item.name}}"
  with_filetree: ./nvim/lua
  when: item.is_dir == false

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL