Example of a Makefile from the ContainerCraft/Kargo project ported to Taskfile.
Last active
August 22, 2024 19:53
-
-
Save usrbinkat/232e376dc664d066b1967e98d93ebe4e to your computer and use it in GitHub Desktop.
Taskfile vs Makefile
This file contains 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
# --- 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 |
This file contains 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
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