Skip to content

Instantly share code, notes, and snippets.

@Goldziher
Last active November 22, 2025 08:54
Show Gist options
  • Select an option

  • Save Goldziher/88bf98d71abdd6be7f42f996396a02a9 to your computer and use it in GitHub Desktop.

Select an option

Save Goldziher/88bf98d71abdd6be7f42f996396a02a9 to your computer and use it in GitHub Desktop.
Taskfile.yaml Shared Conventions - Universal patterns for Task automation across polyglot projects
# TASKFILE SHARED CONVENTIONS
# Central repository for Taskfile.yaml patterns across all projects
# Use this as a reference when standardizing Taskfile.yaml files
version: '3'
# ==============================================================================
# UNIVERSAL TASK NAMING CONVENTIONS
# ==============================================================================
# CORE LIFECYCLE TASKS (all projects should have these)
# - setup : One-time project initialization (install deps, create .env, etc.)
# MUST be idempotent and safe to re-run multiple times
# - update : Update all dependencies to latest versions (cargo upgrade, uv-bump, pnpm up --latest)
# CRITICAL task for dependency management
# - dev : Start development environment (servers, watchers, etc.)
# - build : Build all artifacts (production-ready)
# - test : Run all tests (unit + integration, no coverage)
# - test:coverage : Run tests with coverage reporting
# - check : Run both lint:check AND format:check (no modifications, CI-friendly)
# - lint : Run all linters WITH auto-fix enabled
# - lint:check : Run all linters WITHOUT auto-fix (check-only mode)
# - format : Auto-format all code (with modifications)
# - format:check : Check formatting without modifying files (CI-friendly)
# - clean : Remove build artifacts and caches
# - clean:all : Deep clean including dependencies
# LANGUAGE-SPECIFIC NAMESPACE CONVENTIONS
# Each language should use its own namespace with consistent sub-tasks:
# rust:
# - rust:install : Install Rust toolchain (if needed)
# - rust:update : cargo upgrade --incompatible && cargo update
# - rust:build : Cargo build (debug or release)
# - rust:test : Cargo test
# - rust:test:coverage : Coverage with tarpaulin/llvm-cov
# - rust:check : cargo check && clippy WITHOUT auto-fix
# - rust:lint : cargo fmt && clippy WITH auto-fix (if applicable)
# - rust:lint:check : cargo fmt --check && clippy (check-only)
# - rust:format : cargo fmt (with modifications)
# - rust:format:check : cargo fmt --check (no modifications)
# - rust:doc : Generate rustdoc
# - rust:bench : Run benchmarks (criterion)
# - rust:clean : Cargo clean
# python:
# - python:install : uv venv + uv sync
# - python:update : uv-bump + uv sync --upgrade
# - python:setup : Alias for python:install (idempotent)
# - python:test : pytest (function-based, *_test.py)
# - python:test:coverage : pytest with coverage (95%+ target)
# - python:lint : ruff check --fix (WITH auto-fix)
# - python:lint:check : ruff check (WITHOUT auto-fix)
# - python:format : ruff format (with modifications)
# - python:format:check: ruff format --check (no modifications)
# - python:typecheck : mypy --strict
# - python:clean : Remove __pycache__, .pytest_cache, .mypy_cache
# typescript: (or ts:, node:, frontend:)
# - typescript:install : pnpm install
# - typescript:update : pnpm up --latest -r
# - typescript:setup : Alias for typescript:install (idempotent)
# - typescript:dev : Next.js dev server / Vite dev
# - typescript:build : Production build
# - typescript:test : vitest (*.spec.ts next to source)
# - typescript:lint : biome lint --write (WITH auto-fix)
# - typescript:lint:check: biome lint (WITHOUT auto-fix)
# - typescript:format : biome format --write (with modifications)
# - typescript:format:check : biome format (no modifications)
# - typescript:typecheck : tsc --noEmit
# - typescript:clean : Remove node_modules, .next, dist
# go:
# - go:install : go mod download
# - go:update : go get -u ./... && go mod tidy + update golangci-lint
# - go:build : go build
# - go:test : go test (table-driven, *_test.go with _test package)
# - go:test:coverage : go test -cover
# - go:lint : golangci-lint run --fix (WITH auto-fix)
# - go:lint:check : golangci-lint run (WITHOUT auto-fix)
# - go:format : gofmt -w / goimports -w (with modifications)
# - go:format:check : gofmt -l / goimports -l (check-only)
# - go:clean : Remove binaries
# ruby:
# - ruby:install : bundle install
# - ruby:update : bundle update
# - ruby:setup : Alias for ruby:install (idempotent)
# - ruby:test : rspec
# - ruby:lint : rubocop --autocorrect-all (WITH auto-fix)
# - ruby:lint:check : rubocop (WITHOUT auto-fix)
# - ruby:format : Alias for ruby:lint (rubocop handles formatting)
# - ruby:format:check: Alias for ruby:lint:check
# - ruby:typecheck : steep check (RBS files in sig/)
# - ruby:clean : Remove .bundle
# java:
# - java:install : Maven/Gradle dependency resolution
# - java:update : mvn versions:use-latest-releases / gradle dependencyUpdates
# - java:setup : Alias for java:install (idempotent)
# - java:build : mvn compile / gradle build
# - java:test : mvn test / gradle test (JUnit 5)
# - java:lint : checkstyle + PMD WITH auto-fix (where applicable)
# - java:lint:check : checkstyle + PMD WITHOUT auto-fix
# - java:format : google-java-format --replace (with modifications)
# - java:format:check: google-java-format --dry-run (check-only)
# - java:clean : mvn clean / gradle clean
# php:
# - php:install : composer install
# - php:update : composer update
# - php:setup : Alias for php:install (idempotent)
# - php:test : phpunit
# - php:lint : phpstan analyse + phpcbf (WITH auto-fix via phpcbf)
# - php:lint:check : phpstan analyse + phpcs (WITHOUT auto-fix)
# - php:format : phpcbf (with modifications, PSR-12)
# - php:format:check : phpcs (check-only, PSR-12)
# - php:clean : Remove vendor
# ==============================================================================
# CROSS-CUTTING NAMESPACE CONVENTIONS
# ==============================================================================
# db: (database operations)
# - db:setup : Create databases and run migrations
# - db:migrate : Run pending migrations
# - db:migrate:rollback : Rollback last migration
# - db:seed : Seed with fixture data
# - db:reset : Drop, recreate, migrate, seed
# - db:console : Open database REPL
# docker:
# - docker:build : Build all Docker images
# - docker:up : Start all services (docker compose up)
# - docker:down : Stop all services
# - docker:logs : Tail logs
# - docker:clean : Remove containers, volumes, images
# fixture: (test data generation)
# - fixture:generate : Generate test fixtures from schemas
# - fixture:validate : Validate fixtures against schemas
# - fixture:sync : Sync fixtures across languages
# ci: (CI/CD operations)
# - ci:validate : Run all validation steps locally
# - ci:build : CI build simulation
# - ci:test : CI test simulation
# release: (versioning and publishing)
# - release:version : Bump version across manifests
# - release:publish : Publish to registries (crates.io, PyPI, npm, etc.)
# - release:tag : Create git tag
# ==============================================================================
# VARIABLE CONVENTIONS
# ==============================================================================
vars:
# Project metadata
PROJECT_NAME: "project-name"
VERSION:
sh: grep '^version = ' Cargo.toml | sed 's/.*"\(.*\)".*/\1/' # or from package.json, etc.
# Build configuration
BUILD_DIR: "build"
DIST_DIR: "dist"
TARGET_DIR: "target"
# Rust configuration
CARGO_TARGET_DIR: "{{.TARGET_DIR}}"
RUST_LOG: "info"
RUSTFLAGS: "-D warnings"
# Python configuration
PYTHON_VERSION: "3.10"
UV_SYSTEM_PYTHON: "1"
PYTEST_ARGS: "-v --tb=short"
COVERAGE_TARGET: "95"
# TypeScript/Node configuration
NODE_ENV: "development"
PNPM_VERSION: "10.17"
# Database configuration
DATABASE_URL: "postgresql://localhost/{{.PROJECT_NAME}}_dev"
TEST_DATABASE_URL: "postgresql://localhost/{{.PROJECT_NAME}}_test"
# Docker configuration
COMPOSE_FILE: "docker-compose.yaml"
COMPOSE_PROJECT_NAME: "{{.PROJECT_NAME}}"
# Cross-platform detection
OS:
sh: uname -s | tr '[:upper:]' '[:lower:]'
ARCH:
sh: uname -m
# ==============================================================================
# DEPENDENCY PATTERN CONVENTIONS
# ==============================================================================
# Pattern 1: Sequential dependencies with deps:
# tasks:
# build:
# deps: [lint, test]
# cmds:
# - cargo build --release
# Pattern 2: Parallel execution (default)
# tasks:
# ci:
# cmds:
# - task: rust:lint
# - task: rust:test
# - task: python:lint
# - task: python:test
# Pattern 3: Conditional execution with status:
# tasks:
# setup:
# cmds:
# - pnpm install
# status:
# - test -f node_modules/.bin/next
# Pattern 4: Platform-specific with platforms:
# tasks:
# rust:build:
# platforms: [darwin, linux]
# cmds:
# - cargo build --release
# ==============================================================================
# COMMAND PATTERNS
# ==============================================================================
# Pattern 1: Fail-fast with set -e
# cmds:
# - cmd: |
# set -e
# cargo build
# cargo test
# Pattern 2: Silent commands with silent: true
# tasks:
# version:
# silent: true
# cmds:
# - echo "{{.VERSION}}"
# Pattern 3: Error handling with ignore_error
# tasks:
# clean:
# cmds:
# - cmd: rm -rf target
# ignore_error: true
# Pattern 4: Multi-line with YAML block scalar
# cmds:
# - |
# echo "Starting build..."
# cargo build --release
# echo "Build complete"
# ==============================================================================
# CROSS-PLATFORM SUPPORT PATTERNS
# ==============================================================================
# Pattern 1: OS-specific variables
# vars:
# PYTHON_BIN:
# sh: |
# if [ "{{OS}}" = "darwin" ]; then
# echo ".venv/bin/python"
# else
# echo ".venv/bin/python3"
# fi
# Pattern 2: Platform-specific tasks
# tasks:
# setup:darwin:
# platforms: [darwin]
# cmds:
# - brew install task
#
# setup:linux:
# platforms: [linux]
# cmds:
# - curl -sL https://taskfile.dev/install.sh | sh
# ==============================================================================
# CORE TASK IMPLEMENTATION EXAMPLES
# ==============================================================================
# Example: setup task (MUST be idempotent)
# tasks:
# setup:
# desc: "Install all dependencies and initialize project"
# cmds:
# - task: rust:install
# - task: python:install
# - task: typescript:install
# - task: ruby:install
# - echo "✓ Setup complete - safe to re-run anytime"
# status:
# - test -f .env # Only create .env if missing
# Example: update task (updates all dependencies)
# tasks:
# update:
# desc: "Update all dependencies to latest versions"
# cmds:
# - echo "Updating Rust dependencies..."
# - task: rust:update
# - echo "Updating Python dependencies..."
# - task: python:update
# - echo "Updating TypeScript dependencies..."
# - task: typescript:update
# - prek autoupdate # Update pre-commit hooks
# - echo "✓ All dependencies updated"
# Example: check task (CI-friendly, no modifications)
# tasks:
# check:
# desc: "Run all checks without modifications (lint + format checks)"
# cmds:
# - task: lint:check
# - task: format:check
# Example: lint task (WITH auto-fix)
# tasks:
# lint:
# desc: "Run all linters with auto-fix enabled"
# cmds:
# - task: rust:lint
# - task: python:lint
# - task: typescript:lint
# - task: go:lint
# Example: lint:check task (WITHOUT auto-fix)
# tasks:
# lint:check:
# desc: "Run all linters in check-only mode (no modifications)"
# cmds:
# - task: rust:lint:check
# - task: python:lint:check
# - task: typescript:lint:check
# - task: go:lint:check
# Example: format task (WITH modifications)
# tasks:
# format:
# desc: "Format all code with modifications"
# cmds:
# - task: rust:format
# - task: python:format
# - task: typescript:format
# - task: go:format
# Example: format:check task (WITHOUT modifications)
# tasks:
# format:check:
# desc: "Check code formatting without modifications"
# cmds:
# - task: rust:format:check
# - task: python:format:check
# - task: typescript:format:check
# - task: go:format:check
# ==============================================================================
# PROJECT TYPE SPECIFIC PATTERNS
# ==============================================================================
# POLYGLOT PROJECTS (kreuzberg, html-to-markdown)
# - Version sync from single source (Cargo.toml)
# - Parallel builds for all bindings
# - Unified test:all that runs tests in all languages
# - E2E test generation from fixtures
# - FFI library builds with LD_LIBRARY_PATH management
# MONOREPO PROJECTS (fincom, pronestic)
# - Service-specific namespaces (backend:, frontend:, indexer:)
# - Docker Compose orchestration for all services
# - Database per service with multi-schema support
# - Environment profiles (dev, staging, prod)
# WEB FRAMEWORK PROJECTS (spikard)
# - Benchmark harness with criterion
# - Fixture-driven test generation
# - OpenAPI code generation
# - Integration tests with real HTTP server
# FULL-STACK PROJECTS (grantflow)
# - Frontend + backend coordination
# - Cloud SQL remote management
# - E2E environment with emulators
# - Multi-tenant data isolation
# ==============================================================================
# BEST PRACTICES
# ==============================================================================
# 1. Task naming: lowercase with colons (namespace:task:subtask)
# 2. Description on all public tasks (desc: "...")
# 3. Internal tasks with prefix 'internal:' or hidden via 'internal: true'
# 4. Variables in SCREAMING_SNAKE_CASE
# 5. Use {{.VAR}} for templating, not $VAR
# 6. Prefer task: over direct command invocation for composition
# 7. Always specify working dir if not root (dir: "path")
# 8. Use sources: and generates: for incremental builds
# 9. Group related tasks in namespaces
# 10. Lock files (uv.lock, pnpm-lock.yaml) should be committed
# 11. setup task should be idempotent (safe to run multiple times)
# 12. clean should not delete lock files or .env
# 13. Use silent: true for tasks that output structured data
# 14. Avoid hard-coded paths; use variables
# ==============================================================================
# ANTI-PATTERNS TO AVOID
# ==============================================================================
# ❌ DON'T: Use shell-specific syntax (use POSIX sh)
# ❌ DON'T: Hard-code absolute paths
# ❌ DON'T: Mix concerns in single task (lint + test + build)
# ❌ DON'T: Skip error handling (use set -e or ignore_error intentionally)
# ❌ DON'T: Create circular dependencies between tasks
# ❌ DON'T: Use non-descriptive task names (a, b, run1, etc.)
# ❌ DON'T: Duplicate commands across tasks (extract to shared task)
# ❌ DON'T: Ignore cross-platform compatibility
# ❌ DON'T: Use deprecated Task v2 syntax
# ❌ DON'T: Commit .env files (use .env.example)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment