--- layout: layouts/base.njk permalink: / ---

Taskfile Build

Run any project.

[![.forgejo/workflows/build.yml](https://codeberg.org/Mint-System/taskfile.build/badges/workflows/build.yml/badge.svg)](https://codeberg.org/Mint-System/taskfile.build/actions?workflow=build.yml) --- The task file is a simple bash script and standardized interface for any software project. It is to be understood as a software development pattern to standardize the installation, configuration and execution of different software frameworks. - 🛠️ **Configuration**: Install and configure software and tools with ease. - 🐳 **Docker Build**: Build and publish Docker images for your project. - 🔑 **KeePass / Pass**: Store and load secrets from KeePass and pass. - 📄 **.env / dotenv**: Manage multiple dotenv files for your projects. - 🔄 **CI Pipelines**: Simplify CI pipelines by making the executed task reproducible. - 📚 **Library commands**: A collection of reusable commands for common scripting tasks. ## Specification The specification is a short guide to set up a task file for a Python project. Create a file `task` in your project. ```bash touch task ``` Ensure it is executable. ```bash chmod +x task ``` First add the bash shebang. ```bash #!/usr/bin/env bash ``` Then append the abort on error setting. ```bash set -e ``` Next add the dynamic width help table function. ```bash help-table() { local -a rows local max_cmd=7 max_opt=6 max_desc=11 rows+=("Command|Option|Description") rows+=("help|[grep]|Show help for commands.") rows+=("install||Install build dependencies.") rows+=("lint||Run pre-commit.") rows+=("version||Show version of required tools.") for row in "${rows[@]}"; do IFS='|' read -r cmd opt desc <<< "$row" (( ${#cmd} > max_cmd )) && max_cmd=${#cmd} (( ${#opt} > max_opt )) && max_opt=${#opt} (( ${#desc} > max_desc )) && max_desc=${#desc} done printf '| %-*s | %-*s | %-*s |\n' \ "$max_cmd" "Command" \ "$max_opt" "Option" \ "$max_desc" "Description" printf '|-%*s-|-%*s-|-%*s-|\n' \ "$max_cmd" "$(printf '%*s' "$max_cmd" '' | tr ' ' '-')" \ "$max_opt" "$(printf '%*s' "$max_opt" '' | tr ' ' '-')" \ "$max_desc" "$(printf '%*s' "$max_desc" '' | tr ' ' '-')" local first_row=true for row in "${rows[@]:1}"; do IFS='|' read -r cmd opt desc <<< "$row" if [[ "$cmd" =~ ^===.*===$ ]]; then group_name="${cmd/===/}" group_name="${group_name/===/}" if [ "$first_row" = true ]; then first_row=false else printf '|-%*s-|-%*s-|-%*s-|\n' \ "$max_cmd" "$(printf '%*s' "$max_cmd" '' | tr ' ' '-')" \ "$max_opt" "$(printf '%*s' "$max_opt" '' | tr ' ' '-')" \ "$max_desc" "$(printf '%*s' "$max_desc" '' | tr ' ' '-')" fi local left_pad=$(( (max_cmd - ${#group_name}) / 2 )) local right_pad=$(( max_cmd - left_pad - ${#group_name} )) printf '| %*s%s%*s | %*s | %*s |\n' \ "$left_pad" "" \ "$group_name" \ "$right_pad" "" \ "$max_opt" "" \ "$max_desc" "" printf '|-%*s-|-%*s-|-%*s-|\n' \ "$max_cmd" "$(printf '%*s' "$max_cmd" '' | tr ' ' '-')" \ "$max_opt" "$(printf '%*s' "$max_opt" '' | tr ' ' '-')" \ "$max_desc" "$(printf '%*s' "$max_desc" '' | tr ' ' '-')" else first_row=false printf '| %-*s | %-*s | %-*s |\n' \ "$max_cmd" "$cmd" \ "$max_opt" "$opt" \ "$max_desc" "$desc" fi done } ``` And the help function that shows and filters the table. ```bash help() { local grep_pattern echo if [[ -n "$1" ]]; then grep_pattern="$1" help-table | grep -i "$grep_pattern" | column -t -s'|' else echo 'task [options]' echo echo 'commands:' echo help-table fi echo } ``` Implement the actual command functions. ```bash install() { echo 'Setup venv and install Python dependencies' uv venv source .venv/bin/activate uv pip install pre-commit } lint() { source .venv/bin/activate echo 'Run pre-commit' pre-commit run --all-file } version() { uv --version } ``` Finish the task file with command switch cases. ```bash if [[ "$1" == *","* ]]; then # Split comma-separated commands IFS=',' read -ra COMMANDS <<< "$1" for cmd in "${COMMANDS[@]}"; do # Trim whitespace cmd=$(echo "$cmd" | xargs) if declare -f "$cmd" > /dev/null; then "$cmd" else echo "Unknown command: $1" help "$@" exit 1 fi done elif declare -f "$1" > /dev/null; then "$1" "${@:2}" else case "$1" in all) install lint ;; *) echo "Unknown command: $1" help exit 1 ;; esac fi ``` These are the main parts of every task file script. Now see [usage](/usage) on how to use the task file. ## Development Checkout the [development](/development) page for details.