Skip to content

Instantly share code, notes, and snippets.

@usrbinkat
Last active August 22, 2024 19:53
Show Gist options
  • Save usrbinkat/232e376dc664d066b1967e98d93ebe4e to your computer and use it in GitHub Desktop.
Save usrbinkat/232e376dc664d066b1967e98d93ebe4e to your computer and use it in GitHub Desktop.
Taskfile vs Makefile

Simple comparison of Makefile vs Taskfile

Example of a Makefile from the ContainerCraft/Kargo project ported to Taskfile.

# --- Global Variables ---
LOWERCASE_GITHUB_REPOSITORY := $(shell echo ${GITHUB_REPOSITORY} | tr '[:upper:]' '[:lower:]')
REPO_NAME := $(shell echo ${LOWERCASE_GITHUB_REPOSITORY} | awk -F '/' '{print $$2}')
REPO_ORG := $(shell echo ${LOWERCASE_GITHUB_REPOSITORY} | awk -F '/' '{print $$1}')
PROJECT ?= $(or $(REPO_NAME),kargo)
DEPLOYMENT ?= $(or $(ENVIRONMENT),ci)
# Check if PULUMI_BACKEND_URL starts with 'file://'
ifeq ($(findstring file://,$(PULUMI_BACKEND_URL)),file://)
ORGANIZATION = organization
$(info ORGANIZATION: ${ORGANIZATION})
else
ORGANIZATION = ${GITHUB_USER}
$(info ORGANIZATION is set to ${GITHUB_USER})
endif
# Set Pulumi stack identifier to <organization>/<project>/<deployment>
PULUMI_STACK_IDENTIFIER := ${ORGANIZATION}/${PROJECT}/${DEPLOYMENT}
# Escape special characters in sensitive tokens
ESCAPED_PAT := $(shell echo "${PULUMI_ACCESS_TOKEN}" | sed -e 's/[\/&]/\\&/g')
ESCAPED_GITHUB_TOKEN := $(shell echo "${GITHUB_TOKEN}" | sed -e 's/[\/&]/\\&/g')
# Define file paths for configurations
KUBE_CONFIG_FILE := $$(pwd)/.kube/config
TALOS_CONFIG_FILE := $$(pwd)/.talos/config
PULUMI_HOME := $$(pwd)/.pulumi
# Check if PULUMI_ACCESS_TOKEN is set
ifeq ($(ESCAPED_PAT),)
$(warning PULUMI_ACCESS_TOKEN is not set)
endif
# Check if GITHUB_TOKEN is set
ifeq ($(ESCAPED_GITHUB_TOKEN),)
$(warning GITHUB_TOKEN is not set)
endif
# --- Targets ---
.PHONY: help detect-arch pulumi-login pulumi-up up talos-gen-config talos-cluster clean clean-all act konductor test-talos stop force-terminating-ns
# --- Default Command ---
all: help
# --- Help ---
# Display available commands
help:
@echo "Available commands:"
@echo " help - Display this help message."
@echo " login - Authenticate with Pulumi."
@echo " esc ENV=foobar - Run Pulumi ESC environment. Default: ENV='kubernetes'."
@echo " up - Deploy Pulumi infrastructure."
@echo " pulumi-down - Destroy deployed Pulumi infrastructure."
@echo " talos-cluster - Deploy a Talos Kubernetes cluster."
@echo " talos-config - Generate and validate Talos configuration."
@echo " talos - Create and configure a Talos Kubernetes cluster."
@echo " clean - Clean up resources."
@echo " clean-all - Perform 'clean' and remove Docker volumes."
@echo " act - Test GitHub Actions locally."
@echo " konductor - Maintain .github/devcontainer submodule."
@echo " test - Run setup tests."
@echo " stop - Stop Github Codespaces."
# --- Detect Architecture ---
detect-arch:
@echo $(shell uname -m | awk '{ if ($$1 == "x86_64") print "amd64"; else if ($$1 == "aarch64" || $$1 == "arm64") print "arm64"; else print "unknown" }')
# --- Pulumi Login ---
pulumi-login:
@echo "Logging into Pulumi..."
@direnv allow || true
@PULUMI_HOME=${PULUMI_HOME} PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN} pulumi login \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g' || true
@PULUMI_HOME=${PULUMI_HOME} pulumi install || true
@set -ex; PULUMI_HOME=${PULUMI_HOME} pulumi stack select --create ${PULUMI_STACK_IDENTIFIER} || true
@echo "Login successful."
# --- Pulumi Deployment ---
pulumi-up:
@echo "Deploying Pulumi infrastructure..."
@KUBECONFIG=${KUBE_CONFIG_FILE} PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN} PULUMI_HOME=${PULUMI_HOME} \
pulumi up --yes --skip-preview --refresh --continue-on-error --stack ${PULUMI_STACK_IDENTIFIER} \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g' || true
@KUBECONFIG=${KUBE_CONFIG_FILE} PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN} PULUMI_HOME=${PULUMI_HOME} \
pulumi up --yes --skip-preview --refresh --continue-on-error --stack ${PULUMI_STACK_IDENTIFIER} \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g' || true
@KUBECONFIG=${KUBE_CONFIG_FILE} PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN} PULUMI_HOME=${PULUMI_HOME} \
pulumi up --yes --skip-preview --refresh --continue-on-error --stack ${PULUMI_STACK_IDENTIFIER} \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g'
@echo "Deployment complete."
pulumi-down:
@echo "Deploying Pulumi infrastructure..."
@KUBECONFIG=${KUBE_CONFIG_FILE} PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN} PULUMI_HOME=${PULUMI_HOME} \
pulumi down --yes --skip-preview --refresh --stack ${PULUMI_STACK_IDENTIFIER} \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g' || \
KUBECONFIG=${KUBE_CONFIG_FILE} PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN} PULUMI_HOME=${PULUMI_HOME} PULUMI_K8S_DELETE_UNREACHABLE=true \
pulumi down --yes --skip-preview --refresh --stack ${PULUMI_STACK_IDENTIFIER} \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g' || true
@echo "Deployment complete."
login: pulumi-login
up: pulumi-login pulumi-up wait-all-pods
down: pulumi-login pulumi-down
# ----------------------------------------------------------------------------------------------
# --- Control Flow ---
# ----------------------------------------------------------------------------------------------
# --- Wait for All Pods Ready ---
wait-all-pods:
@echo "Waiting for all pods in the cluster to be ready..."
@bash -c 'until [ "$$(kubectl get pods --all-namespaces --no-headers | grep -v "Running\|Completed\|Succeeded" | wc -l)" -eq 0 ]; do echo "Waiting for pods to be ready..."; sleep 5; done'
@kubectl get pods --all-namespaces --show-labels --kubeconfig ${KUBE_CONFIG_FILE}
@echo "All pods in the cluster are ready."
# ----------------------------------------------------------------------------------------------
# --- Talos Kubernetes Cluster ---
# ----------------------------------------------------------------------------------------------
# --- Talos Configuration ---
talos-gen-config:
@echo "Generating Talos Config..."
@mkdir -p ${HOME}/.kube .kube .pulumi .talos
@touch ${HOME}/.kube/config ${KUBE_CONFIG_FILE} ${TALOS_CONFIG_FILE}
@chmod 600 ${HOME}/.kube/config ${KUBE_CONFIG_FILE} ${TALOS_CONFIG_FILE}
@talosctl gen config kargo https://10.5.0.2:6443 \
--config-patch @.talos/patch/machine.yaml --output .talos/manifest --force
@echo "Talos Config generated."
# @talosctl validate --mode container \
# --config .talos/manifest/controlplane.yaml
# @talosctl validate --mode container \
# --config .talos/manifest/worker.yaml
# --- Talos Cluster ---
# --workers 0 --memory-workers 8192
talos-cluster: detect-arch talos-gen-config
@echo "Creating Talos Kubernetes Cluster..."
set -ex; talosctl cluster create --provisioner docker \
--arch=$$(make detect-arch | grep -E "arm64|amd64") \
--user-disk "/var/mnt/hostpath-provisioner:8" \
--config-patch @.talos/patch/machine.yaml \
--exposed-ports 30590:30590/tcp \
--controlplanes 1 --memory 8192 \
--context talos-kargo-docker \
--name talos-kargo-docker \
--init-node-as-endpoint \
--workers 0
@PULUMI_HOME=${PULUMI_HOME} pulumi config set --path kubernetes.distribution talos || true
@PULUMI_HOME=${PULUMI_HOME} pulumi config set --path kubernetes.context admin@talos-kargo-docker || true
@PULUMI_HOME=${PULUMI_HOME} pulumi config set --path cilium.enabled false || true
@PULUMI_HOME=${PULUMI_HOME} pulumi config set --path multus.enabled false || true
@PULUMI_HOME=${PULUMI_HOME} pulumi config set --path kubernetes.kubeconfig $$(pwd)/.kube/config || true
@echo "Talos Cluster provisioning..."
# --- Wait for Talos Cluster Ready ---
talos-ready:
@echo "Waiting for Talos Cluster to be ready..."
@bash -c 'until kubectl --kubeconfig ${KUBE_CONFIG_FILE} wait --for=condition=Ready pod -l k8s-app=kube-scheduler --namespace=kube-system --timeout=180s; do echo "Waiting for kube-scheduler to be ready..."; sleep 5; done' || true
@bash -c 'until kubectl --kubeconfig ${KUBE_CONFIG_FILE} wait --for=condition=Ready pod -l k8s-app=kube-controller-manager --namespace=kube-system --timeout=180s; do echo "Waiting for kube-controller-manager to be ready..."; sleep 5; done' || true
@bash -c 'until kubectl --kubeconfig ${KUBE_CONFIG_FILE} wait --for=condition=Ready pod -l k8s-app=kube-apiserver --namespace=kube-system --timeout=180s; do echo "Waiting for kube-apiserver to be ready..."; sleep 5; done' || true
@echo "Talos Cluster is ready."
# --- Talos ---
talos: clean-all talos-cluster talos-ready wait-all-pods
@echo "Talos Cluster ready."
# ----------------------------------------------------------------------------------------------
# --- Maintenance ---
# ----------------------------------------------------------------------------------------------
# --- Cleanup ---
clean: login
@echo "Cleaning up resources..."
@sudo talosctl cluster destroy --name talos-kargo-docker \
|| echo "Talos cluster not found."
@docker rm --force talos-kargo-docker-controlplane-1 talos-kargo-docker-worker-1 \
|| echo "Talos containers not found."
@echo "Waiting for 5 seconds..." && sleep 5
@PULUMI_HOME=${PULUMI_HOME} pulumi cancel --yes --stack ${PULUMI_STACK_IDENTIFIER} 2>/dev/null || true
@PULUMI_HOME=${PULUMI_HOME} pulumi down --yes --skip-preview --refresh --stack ${PULUMI_STACK_IDENTIFIER} \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g' || true
@PULUMI_HOME=${PULUMI_HOME} pulumi down --yes --skip-preview --refresh --stack ${PULUMI_STACK_IDENTIFIER} \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g' || true
@PULUMI_HOME=${PULUMI_HOME} pulumi cancel --yes --stack ${PULUMI_STACK_IDENTIFIER} 2>/dev/null || true
@rm -rf .talos/manifest/*
@rm -rf .kube/config
@echo "Cleanup complete."
clean-all: clean
@echo "Performing extended cleanup..."
@echo "Extended cleanup complete."
# --- GitHub Actions Testing ---
act:
@echo "Testing GitHub Workflows locally..."
@direnv allow
@act --container-options "--privileged" --rm \
--var GITHUB_TOKEN=${GITHUB_TOKEN} \
--var PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN} \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g'
@echo "GitHub Workflow Test Complete."
# --- Maintain Devcontainer ---
konductor:
@git submodule update --init .github/konductor
@git submodule update --remote --merge .github/konductor
@rsync -av .github/konductor/.devcontainer/* .devcontainer
@docker pull ghcr.io/containercraft/konductor:latest
@echo "Devcontainer updated."
test-talos: talos pulumi-up
@echo "Talos test complete."
# --- Stop Codespaces ---
stop: clean
@echo "Stopping Codespaces..."
@gh codespace --codespace ${CODESPACE_NAME} stop
@echo "Codespaces stopped."
# --- Stop Codespaces ---
force-terminating-ns:
@kubectl proxy & \
PROXY_PID=$$! ;\
sleep 2 ;\
kubectl get namespaces --field-selector=status.phase=Terminating -o json | jq -r '.items[].metadata.name' | while read NAMESPACE ; do \
echo "Clearing finalizers for namespace $$NAMESPACE" ;\
kubectl get namespace $$NAMESPACE -o json | jq '.spec = {"finalizers":[]}' > temp-$$NAMESPACE.json ;\
curl -k -H "Content-Type: application/json" -X PUT --data-binary @temp-$$NAMESPACE.json 127.0.0.1:8001/api/v1/namespaces/$$NAMESPACE/finalize ;\
rm -f temp-$$NAMESPACE.json ;\
done ;\
kill $$PROXY_PID
version: "3"
dotenv:
- .env
vars:
deployment: "{{.DEPLOYMENT | default `ci`}}"
project: "{{.PROJECT | default `kargo`}}"
organization: "{{.ORGANIZATION | default .GITHUB_USER}}"
pulumi_dir: "{{.PWD}}/.pulumi"
kube_dir: "{{.PWD}}/.kube"
kube_config_file: "{{.kube_dir}}/config"
pulumi_stack_identifier: "{{.organization}}/{{.project}}/{{.deployment}}"
talos_dir: "{{.PWD}}/.talos"
talos_patch: "{{.talos_dir}}/patch/cluster.yaml"
talos_config_file: "{{.talos_dir}}/manifest/talosconfig"
cluster_name: "talos-kargo-docker"
exposed_ports: "30590:30590/tcp"
memory: "8192"
arch:
sh: |
arch=$(uname -m)
if [ "$arch" = "x86_64" ]; then
echo "amd64"
elif [ "$arch" = "aarch64" ] || [ "$arch" = "arm64" ]; then
echo "arm64"
else
echo "unknown"
fi
tasks:
##################################################################################
# Meta & Utility Tasks
# TODO: @RUNME remove `source .envrc` when runme support lands for direnv
default:
desc: "Run all tasks to set up and configure a Kargo Kubevirt Kubernetes Platform."
cmds:
- task: deploy
printenv:
desc: "Print environment variables."
cmds:
- /usr/bin/echo "{{.kube_dir}}"
init:
desc: "Initialize directories and configuration files."
cmds:
- mkdir -p .kube .pulumi .talos
- touch {{.kube_config_file}} {{.talos_config_file}}
- chmod 600 {{.kube_config_file}} {{.talos_config_file}}
login:
desc: "Authenticate with Pulumi."
cmds:
- task: init
- source .envrc && pulumi login
- source .envrc && pulumi install
deploy:
desc: "Deploy Kubernetes + Kargo Kubevirt PaaS IaC"
deps:
- iac-cancel
cmds:
- task: iac-deploy
all-pods-ready:
desc: "Wait for all Kubernetes pods in the cluster to be ready."
cmds:
- bash -c 'until [ "$(kubectl get pods --all-namespaces --no-headers | grep -v "Running\\|Completed\\|Succeeded" | wc -l)" -eq 0 ]; do echo "Waiting for pods..."; sleep 5; done'
- kubectl get pods --all-namespaces --show-labels --kubeconfig {{.kube_config_file}}
destroy:
desc: "Clean up and destroy all Pulumi and Kubernetes resources."
cmds:
- task: destroy
act:
desc: "Test GitHub Actions locally using 'act'."
cmds:
- act --container-options "--privileged" --rm --var GITHUB_TOKEN=${GITHUB_TOKEN} --var PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN}
clean:
desc: "Clean up all local Kargo resources."
cmds:
- task: iac-cancel
- task: iac-clean
clean-all:
desc: "Clean up all local Kargo resources."
deps:
- kubernetes-clean
- clean
cmds:
- ssh-keygen -f "/home/vscode/.ssh/known_hosts" -R "[127.0.0.1]:30590" 2>/dev/null || true
- rm -rf .talos/manifest/* .kube/config .ssh/known_hosts 2>/dev/null || true
- rm ${HOME}/.pulumi ${HOME}/.kube ${HOME}/.talos 2>/dev/null || true
stop:
desc: "Stop the GitHub Codespace."
cmds:
- task: clean
- gh codespace --codespace ${CODESPACE_NAME} stop
##################################################################################
# Demo VM Tasks
vm-deploy:
desc: "Enable the built in pulumi Ubuntu vm iac feature"
cmds:
- source .envrc && pulumi config set --path vm.enabled true
- source .envrc && pulumi up --yes --skip-preview --refresh --stack {{.pulumi_stack_identifier}}
vm-destroy:
desc: "Enable the built in pulumi Ubuntu vm iac feature"
cmds:
- source .envrc && pulumi config set --path vm.enabled false
- source .envrc && pulumi up --yes --skip-preview --refresh --stack {{.pulumi_stack_identifier}}
##################################################################################
# Pulumi Tasks
configure:
desc: "Configure Pulumi stack settings."
cmds:
- source .envrc && pulumi stack select --create {{.pulumi_stack_identifier}} || true
- source .envrc && pulumi config set --path kubernetes.distribution talos
- source .envrc && pulumi config set --path kubernetes.context admin@{{.cluster_name}}
- source .envrc && pulumi config set --path kubernetes.kubeconfig {{.kube_config_file}}
- source .envrc && pulumi config set --path cilium.enabled false
- source .envrc && pulumi config set --path multus.enabled false
- source .envrc && pulumi config set --path vm.enabled false
iac-deploy:
desc: "Deploy Pulumi infrastructure."
cmds:
- task: iac-cancel
- source .envrc && pulumi up --yes --skip-preview --refresh --continue-on-error --stack {{.pulumi_stack_identifier}} || true
- task: all-pods-ready
- source .envrc && pulumi up --yes --skip-preview --refresh --stack {{.pulumi_stack_identifier}}
- task: all-pods-ready
iac-destroy:
desc: "Destroy Pulumi infrastructure."
cmds:
- task: iac-cancel
- |
source .envrc
pulumi down --yes --skip-preview --refresh --stack {{.pulumi_stack_identifier}} || true
pulumi down --yes --skip-preview --refresh --stack {{.pulumi_stack_identifier}}
iac-cancel:
desc: "Cancel the Pulumi update."
cmds:
- source .envrc && pulumi cancel --yes --stack {{.pulumi_stack_identifier}} 2>/dev/null || true
iac-clean:
desc: "Clean up all Pulumi resources."
cmds:
- task: iac-cancel
- source .envrc && pulumi down --yes --skip-preview --refresh --stack {{.pulumi_stack_identifier}} 2>/dev/null || true
##################################################################################
# Talos Tasks
kubernetes-gen-config:
desc: "Generate Talos cluster configuration."
cmds:
- talosctl gen config {{.project}} https://10.0.5.2:6443 --config-patch @{{.talos_patch}} --force --output .talos/manifest --context {{.cluster_name}}
kubernetes-deploy:
desc: "Deploy Kubernetes cluster."
cmds:
- task: init
- |
talosctl cluster create \
--arch={{.arch}} \
--provisioner docker \
--init-node-as-endpoint \
--config-patch @{{.talos_patch}} \
--controlplanes 1 \
--memory {{.memory}} \
--exposed-ports {{.exposed_ports}} \
--context {{.cluster_name}} \
--name {{.cluster_name}} \
--workers 0 --crashdump
kubernetes-ready:
desc: "Wait for the Talos cluster control plane components to be ready."
cmds:
- bash -c 'until kubectl --kubeconfig {{.kube_config_file}} wait --for=condition=Ready pod -l k8s-app=kube-scheduler --namespace=kube-system --timeout=180s; do echo "Waiting for kube-scheduler..."; sleep 5; done' || true
- bash -c 'until kubectl --kubeconfig {{.kube_config_file}} wait --for=condition=Ready pod -l k8s-app=kube-controller-manager --namespace=kube-system --timeout=180s; do echo "Waiting for kube-controller-manager..."; sleep 5; done' || true
- bash -c 'until kubectl --kubeconfig {{.kube_config_file}} wait --for=condition=Ready pod -l k8s-app=kube-apiserver --namespace=kube-system --timeout=180s; do echo "Waiting for kube-apiserver..."; sleep 5; done' || true
kubernetes-clean:
desc: "Clean up all Kubernetes resources."
cmds:
- talosctl cluster destroy --name {{.cluster_name}} 2>/dev/null || true
- docker rm --force {{.cluster_name}}-controlplane-1 2>/dev/null || true
kubernetes:
desc: "Complete setup and configuration of a Kubernetes cluster."
deps:
- clean
- kubernetes-clean
cmds:
- task: init
- task: kubernetes-gen-config
- task: kubernetes-deploy
- task: kubernetes-ready
- task: all-pods-ready
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment