-
-
Save thimslugga/5a2150232a3499509ca1d2417854382b to your computer and use it in GitHub Desktop.
A justfile template
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env just --justfile | |
# -*- mode: justfile -*- | |
# https://just.systems/man/en/introduction.html | |
# ============================================================================== | |
# Settings | |
# ============================================================================== | |
# Enable unstable features | |
set unstable := false | |
# Set the shell used to execute recipes. Array form is recommended. | |
# -u: Treat unset variables as an error. | |
# -c: Read commands from string. | |
set shell := ["bash", "-uc"] | |
#set shell := ["zsh", "-cu"] | |
# Set command used to invoke recipes with empty [script] attribute. | |
#set script-interpreter := ['sh', '-eu'] | |
# Allow recipes appearing later to override earlier recipes with the same name. | |
set allow-duplicate-recipes := false | |
# Allow variables appearing later to override earlier variables with the same name. | |
set allow-duplicate-variables := false | |
# Allow positional arguments ($1, $2...) in recipes (legacy style). | |
# Generally prefer named arguments or variadic arguments. | |
set positional-arguments := true | |
# Export variables defined in the Justfile to the environment of recipes. | |
set export := true | |
# Load variables from a .env file in the Justfile's directory. | |
# Create a file named `.env` with VAR=VALUE pairs. | |
set dotenv-load := true | |
# Set the working directory for recipes *relative to the Justfile directory*. | |
#set working-directory := "build" | |
# ============================================================================== | |
# Variables and Constants | |
# ============================================================================== | |
# Simple assignment (evaluated once at parse time) | |
SIMPLE_VAR := "This is a simple variable" | |
VERSION := "1.0.0" | |
# Evaluated assignment (shell command executed at parse time) | |
CURRENT_DIR = `pwd` | |
GIT_BRANCH = `git rev-parse --abbrev-ref HEAD` | |
# Exported variable (available in recipe environments because `set export` is true) | |
EXPORTED_VAR := "This variable is exported to the shell environment" | |
# Environment variable override: Just will use the environment's value if set, | |
# otherwise it uses this default. | |
# Try running: `MY_NAME="From Env" just show-vars` | |
MY_NAME := "Default User" | |
# Variables available for override on the command line: | |
# `just show-vars override_me="New Value"` | |
override_me := "Initial Value" | |
# Conditional assignment using built-in functions | |
# Available functions: arch(), os(), os_family(), env_var(), env_var_or_default(), | |
# invocation_directory(), justfile_directory(), num_cpus(), just_executable() | |
TARGET_OS := if os() == "linux" { "Linux" } else if os() == "macos" { "macOS" } else if os() == "windows" { "Windows" } else { "Unknown OS" } | |
BUILD_DIR := if os_family() == "windows" { "build\\win" } else { "build/unix" } | |
# String interpolation | |
GREETING := "Hello, {{MY_NAME}}!" # Uses the potentially overridden value of MY_NAME | |
# ============================================================================== | |
# Aliases | |
# ============================================================================== | |
#alias b := build | |
#alias t := test | |
#alias d := deploy | |
#alias c := clean | |
# ============================================================================== | |
# Recipes | |
# ============================================================================== | |
# Default recipe (runs if `just` is called without arguments) | |
# Depends on the 'hello' recipe. | |
default: hello build | |
@_list: | |
just --justfile {{ justfile() }} --list --unsorted | |
echo "" | |
echo "Available variables:" | |
just --evaluate | sed 's/^/ /' | |
echo "" | |
echo "Override variables using 'just key=value ...' (also ALL_UPPERCASE ones)" | |
[doc('Evaluate and return all just variables')] | |
evaluate: | |
@just --evaluate | |
# Simple recipe with no dependencies or arguments | |
hello: | |
# '@' prefix suppresses echoing the command itself | |
@echo "====================================" | |
@echo "{{GREETING}}" # Interpolates the GREETING variable | |
@echo "Running just version: {{just_executable()}}" | |
@echo "====================================" | |
[doc('Return system information')] | |
system-info: | |
@echo "os: {{ os() }}" | |
@echo "family: {{ os_family() }}" | |
@echo "architecture: {{ arch() }}" | |
@echo "home directory: {{ home_directory() }}" | |
# Recipe with dependencies. 'build' runs before 'test'. | |
# Dependencies are always run, even if the target is up-to-date. | |
build: _private_setup | |
@echo "Building project version {{VERSION}} for {{TARGET_OS}} in {{BUILD_DIR}}..." | |
mkdir -p "{{BUILD_DIR}}" | |
touch "{{BUILD_DIR}}/artifact.built" | |
test: build | |
@echo "Testing the build artifact..." | |
@echo "Checking existence: {{BUILD_DIR}}/artifact.built" | |
test -f "{{BUILD_DIR}}/artifact.built" | |
@echo "Tests passed!" | |
deploy: test | |
@echo "Deploying version {{VERSION}}..." | |
# Simulate deployment | |
clean: _private_cleanup | |
@echo "Cleaning up build artifacts..." | |
rm -rf "{{BUILD_DIR}}" | |
rm -f artifact.tar.gz | |
@echo "Clean complete." | |
# Recipe with required arguments | |
greet NAME: | |
@echo "Greetings, {{NAME}}!" | |
# Recipe with arguments with default values | |
configure ENVIRONMENT="development": | |
@echo "Configuring for environment: {{ENVIRONMENT}}" | |
@# Use `just configure` or `just configure production` | |
# Recipe with variadic arguments (collects all extra arguments) | |
# Use '+' prefix. The variable 'ARGS' will be a space-separated string. | |
process +ARGS: | |
@echo "Processing arguments:" | |
@# Using shell loop to iterate through space-separated args | |
@for arg in {{ARGS}}; do \ | |
echo " - Got arg: $$arg"; \ | |
done | |
# Recipe demonstrating positional arguments (requires `set positional-arguments`) | |
# Usage: `just positional first second third` | |
positional $arg1 $arg2="default_val" $arg3="another_default": | |
@echo "Positional Args:" | |
@echo " Arg 1: {{arg1}}" | |
@echo " Arg 2: {{arg2}}" | |
@echo " Arg 3: {{arg3}}" | |
# Recipe demonstrating capturing all positional args into one var (requires `set positional-arguments`) | |
# Usage: `just positional_all one two three` | |
positional_all *args: | |
@echo "All positional args captured: {{args}}" | |
# Recipe using a different interpreter via shebang | |
# The script content follows the shebang line. | |
python_script: deptask | |
#!/usr/bin/env python | |
import os | |
import platform | |
print(f"Hello from Python inside Just!") | |
print(f"OS: {os.name}, Platform: {platform.system()}, Arch: {platform.machine()}") | |
# Accessing exported env var | |
exported = os.getenv("EXPORTED_VAR", "Not Found") | |
print(f"Accessed exported variable: {exported}") | |
# Another shebang example using Bash explicitly | |
bash_script: | |
#!/bin/bash | |
echo "Hello from an explicit Bash script!" | |
echo "My shell is $SHELL" | |
echo "Current directory is $(pwd)" | |
# Recipe demonstrating backtick command evaluation within the recipe body | |
show_date: | |
@echo "The current date is: `date +'%Y-%m-%d %H:%M:%S'`" | |
@echo "Current git branch evaluated in recipe: `git rev-parse --abbrev-ref HEAD`" | |
# Recipe demonstrating built-in functions | |
show_info: | |
@echo "== System Info ==" | |
@echo "OS Type: {{os()}}" | |
@echo "OS Family: {{os_family()}}" | |
@echo "Architecture: {{arch()}}" | |
@echo "Number of CPUs: {{num_cpus()}}" | |
@echo "== Just Info ==" | |
@echo "Justfile Dir: {{justfile_directory()}}" | |
@echo "Invocation Dir: {{invocation_directory()}}" | |
@echo "== Env Vars ==" | |
@echo "PATH (env_var): {{env_var('PATH')}}" | |
@echo "SHELL (or default): {{env_var_or_default('SHELL', '/bin/sh')}}" | |
@echo "MY_NAME: {{MY_NAME}}" # Shows default or env override | |
@echo "Override Me: {{override_me}}" # Shows default or command-line override | |
# Accessing dotenv var (requires .env file and `set dotenv-load`) | |
@echo "Dotenv Var: {{env_var_or_default('MY_DOTENV_VAR', 'Not Set')}}" | |
# Recipe showing quoting and interpolation edge cases | |
quoting: | |
# Simple quotes are preserved | |
@echo 'Single quotes work' | |
@echo "Double quotes work" | |
# Interpolation works in doubles, not singles | |
@echo "Simple Var: {{SIMPLE_VAR}}" | |
@echo 'Simple Var: {{SIMPLE_VAR}}' # This won't interpolate | |
# Escaping characters | |
@echo "This recipe shows \"quotes\" and backslashes \\ and dollar signs \$" | |
# Complex interpolation | |
COMPLEX_STRING := "Value with 'quotes' and spaces" | |
@echo "Complex variable: {{COMPLEX_STRING}}" | |
# Using expressions in interpolation (less common, usually done in vars) | |
@echo "OS check inline: {{ if os() == 'linux' {'yay linux!'} else {'not linux'} }}" | |
# Recipe demonstrating error handling | |
# '-' prefix: Ignore errors from this command. The recipe continues. | |
# '!' prefix: Run this command even if `just` was invoked with --dry-run. | |
error_handling: | |
@echo "Attempting to remove a non-existent file (will likely fail)..." | |
-rm no_such_file_here.txt | |
@echo "Recipe continued after ignored error." | |
@echo "Now creating a file (forced run even in dry-run)..." | |
!touch i_was_created_anyway.tmp | |
@echo "Now attempting a command that should succeed..." | |
ls . | |
@echo "Finished error handling demo." | |
-rm i_was_created_anyway.tmp # Clean up forced file | |
# ============================================================================== | |
# Recipe Attributes - Modify recipe behavior conditionally | |
# ============================================================================== | |
# [private]: Not shown in `just --list` or `just -l`. Can still be run directly. | |
[private] | |
_private_setup: | |
@echo "(Private) Setting up..." | |
touch private_setup.flag | |
# Recipes starting with '_' are also private by default. | |
_private_cleanup: | |
@echo "(Private) Cleaning up..." | |
rm -f private_setup.flag | |
# [no-cd]: Run the recipe in the directory where `just` was invoked, | |
# not the Justfile's directory (or `working-directory` if set). | |
[no-cd] | |
run_in_invocation_dir: | |
@echo "This recipe runs in: `pwd` (should be where you ran 'just')" | |
@echo "The Justfile is in: {{justfile_directory()}}" | |
# [confirm]: Prompt the user before running the recipe. | |
[confirm] | |
dangerous_action: | |
@echo "WARNING: Performing a potentially dangerous action!" | |
# rm -rf / # Don't actually do this! :) | |
@echo "Action performed (simulation)." | |
# OS-specific recipes | |
[linux] | |
linux_only: | |
@echo "This runs only on Linux. uname: `uname -s`" | |
[macos] | |
macos_only: | |
@echo "This runs only on macOS. uname: `uname -s`" | |
[windows] | |
windows_only: | |
@echo "This runs only on Windows. Systeminfo snippet:" | |
@systeminfo | findstr /B /C:"OS Name" /C:"OS Version" | |
# [unix] is a shorthand for [linux] or [macos] | |
[unix] | |
unix_only: | |
@echo "This runs on Linux or macOS. Family: {{os_family()}}" | |
# ============================================================================== | |
# Imports and Modules - Include other Justfiles | |
# ============================================================================== | |
# Requires a file named `module.just` in the same directory. | |
# Example `module.just`: | |
# ```justfile | |
# # File: module.just | |
# export module_var := "Variable from module" | |
# | |
# # Recipe exported from module | |
# module_recipe NAME="Module User": | |
# echo "Hello {{NAME}} from the module recipe!" | |
# echo "Module variable access: {{module_var}}" | |
# | |
# _private_module_recipe: | |
# echo "This is private to the module" | |
# ``` | |
import "module.just" # Imports recipes and exported variables | |
# Use imported recipe and variable | |
use_module: module_recipe "Just User" # Pass argument to module recipe | |
@echo "Accessing imported variable in main file: {{module_var}}" | |
# Cannot call _private_module_recipe from here | |
# ============================================================================== | |
# Miscellaneous / Edge Cases | |
# ============================================================================== | |
# Task that depends on an imported task | |
depends_on_module: module_recipe | |
@echo "Main task ran after module recipe." | |
# A task just for demonstrating dependencies | |
deptask: | |
@echo "Running dependency task..." | |
# Recipe with line continuations using backslash '\' | |
long_command: | |
@echo "This is the first part of a long command..." \ | |
&& echo "This is the second part, connected by &&" \ | |
&& echo "And this is the third part." | |
# Empty recipe (useful as a dependency placeholder) | |
placeholder: | |
# Recipe showing how exported variables work with subshells | |
check_export: export_check_subshell | |
@echo "Checking EXPORTED_VAR in main recipe: $EXPORTED_VAR" # Access via shell | |
export_check_subshell: | |
#!/bin/bash | |
echo "Checking EXPORTED_VAR in subshell script:" | |
if [ -n "$EXPORTED_VAR" ]; then | |
echo " EXPORTED_VAR is set: '$EXPORTED_VAR'" | |
else | |
echo " EXPORTED_VAR is NOT set." | |
fi | |
echo "Checking SIMPLE_VAR in subshell script (should not be exported):" | |
if [ -n "$SIMPLE_VAR" ]; then | |
echo " SIMPLE_VAR is set: '$SIMPLE_VAR'" | |
else | |
echo " SIMPLE_VAR is NOT set." | |
fi | |
# Final recipe to show variable evaluation timing | |
show_vars: | |
@echo "== Variable Values During Recipe Execution ==" | |
@echo "Simple Var: {{SIMPLE_VAR}}" | |
@echo "Evaluated Dir: {{CURRENT_DIR}}" # Value captured at parse time | |
@echo "Git Branch: {{GIT_BRANCH}}" # Value captured at parse time | |
@echo "Target OS: {{TARGET_OS}}" | |
@echo "Build Dir: {{BUILD_DIR}}" | |
@echo "MY_NAME: {{MY_NAME}}" # Shows resolved value (env > justfile default) | |
@echo "Override Me: {{override_me}}" # Shows resolved value (cmdline > justfile default) | |
@echo "Dotenv Var: {{env_var_or_default('MY_DOTENV_VAR', 'Not Set')}}" | |
@echo "Current Dir (recipe eval): `pwd`" # Value evaluated now |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment