LLMs can't make (file)
S := .sentinels
PROJECT_ROOT := $(abspath ../../)
TARGET_DIR := $(abspath ../../target/aarch64-unknown-linux-musl/debug)
define nl
endef
define CONTAINER
touch $(and $2, $(shell kubectl get -n $1 pod -l app=$2 -o json | jq '.items[0].metadata.creationTimestamp' -r | gsed -e 's/\(.*\)T\(.*\)\([0-9][0-9]\)Z/#t \1\2.\3/;s/[-:]//g;s/#/-/g') $S/$3)$(nl)
touch -A 020000 $@
endef
POD = $(if $2,$(shell kubectl get pod -n $1 -l app=$2 -o name | cut -d/ -f2))
GET_TS = $(if $2,(kubectl exec -n $1 $(POD) -- bash -c 'stat /app/$2 2>/dev/null || stat /app/$2'))
TS = $(and $3,$(shell $(GET_TS) | gsed '/Mod/!{d;b};s/.*: \(.*\) \(.*\)\..*/\1 \2/; s/[-:]//g;s/\([0-9]\+\) \([0-9]\+\)\([0-9][0-9]\)/touch -t \1\2.\3/'))
# Check binary inside container
define CONTAINER_BIN
$(if $3, $(TS) $S/$3)
touch -A 020000 $S/$3
endef
define FRESH_TARGET
E2E_CONTAINER_SENTINELS += $S/$2-$1-container-fresh
$S/$2-$1-container-fresh: $S/$2-$1-binary-fresh
@echo "Restarting $2..."
kubectl rollout restart deployment/$2 -n $1
$$(call CONTAINER,$1,$2,$2-e2e-container)
endef
define FRESH_BINARY_TARGET
E2E_BINARY_SENTINELS += $S/$2-$1-binary-fresh
$S/$2-$1-binary-fresh: $(TARGET_DIR)/$2
kubectl cp $(TARGET_DIR)/$2 -n $1 $(POD):/app/$2
$(call CONTAINER_BIN,$1,$2,$2-e2e-binary-fresh)
endef
define TARGET_CHECK
$(TARGET_DIR)/$1: $(shell fd -e rs -e toml . $(abspath $(PROJECT_ROOT)/$1))
echo $(abspath $(PROJECT_ROOT)/$1)
cd $(PROJECT_ROOT) && cargo zigbuild --target aarch64-unknown-linux-musl --bin $1
touch $$@
endef
$(foreach APP,$E2E_APPS, \
$(eval $(call TARGET_CHECK,$(APP))))
Scared yet?
This is a Makefile I just sunsetted. It’s not that it didn’t work (it worked quite well, actually - the code you’re seeing above generated special .sentinel/SOMETHING files with timestamp equivalent to the files in k8s containters and it worked well.
But I’m a solo dev, so I employ pi.dev agent to help me with various stuff. 7 times out of 10 it works but I noticed that when it comes to Makefiles (not even that complicated as above meta-definitions) it just f***s s**t up.
Because I needed to orchestrate configuration/rollout steps depending on the changes made, Makefile was helpful but after 3 fiascos I stood before the choice:
- Accept 1.5h change tax and update Makefiles manually
- Switch to something else
Since I was already working with YAMLs and agents were able to handle it just fine I looked towards Taskfile. I havemixed feelings about it. On one side, I’ve used it before to do automation, but then on the other hand at some stage it’s becoming cumbersome to have reusable tasks, task templates etc. Makefile is also much terser. Still worth a try.
I asked agent to rewrite Makefile to Taskfile (making sure it has documentation of Taskfile as a context) and it one shotted it. I guess I’m using Taskfile now.
Though I’ve identified few patterns that seems consistent across models (though I haven’t metered it anyway):
| Technology | Rating | Comments |
|---|---|---|
| Cue lang | ★★☆☆☆ | Can do basic transformation, code is verbose and not really reusable. |
| Jsonnet | ★★★☆☆ | When it has guidelines it performs better, by itself it creates hermetic, non-reusable patterns |
| k8s manifests | ★★★★☆ | Consistent and usually successful at requests |
| GNU Make | ☆☆☆☆☆ | Destroys existing patterns, remove (used) constructs which are deemed unneeded, chaos in variable use |
| Go | ★★★☆☆ | Panics during runtime, edge cases usually not handled well, requires handholding when it comes to structure. |
| Rust | ★★★★☆ | If it compiles it usually works, still too happy to unwrap. Very good at following set architecture or founding a new, idiomatic one on demand. |
| Haskell | ★★★★☆ | Similar to Rust. Code is terse, which makes it easy to review. |
| Taskfile | ★★★…? | Able to one shot demands and debugs it quite well. Not enough experience to form opinion though. |
Some things worth mentioning:
GraphMLgeneration seems to be working quite well
Przemysław Alexander Kamiński
vel xlii vel exlee
Powered by hugo and hugo-theme-nostyleplease.