An AI-powered tool that generates human-readable summaries of git changes using tool calling with a self-hosted LLM

Compare changes

Choose any two refs to compare.

Changed files
+123 -71
.tangled
+42
.tangled/workflows/release-amd64.yml
··· 1 + when: 2 + - event: ["push"] 3 + branch: ["main"] 4 + tag: ["v*"] 5 + 6 + engine: kubernetes 7 + image: quay.io/buildah/stable:latest 8 + architecture: amd64 9 + 10 + environment: 11 + IMAGE_REGISTRY: atcr.io 12 + 13 + steps: 14 + - name: Login to registry 15 + command: | 16 + echo "${IMAGE_NAME}" 17 + printenv 18 + echo "${APP_PASSWORD}" | buildah login \ 19 + -u "${TANGLED_REPO_HANDLE}" \ 20 + --password-stdin \ 21 + ${IMAGE_REGISTRY} 22 + 23 + - name: Build amd64 image 24 + command: | 25 + buildah bud \ 26 + --arch amd64 \ 27 + --build-arg TARGETARCH=amd64 \ 28 + --label org.opencontainers.image.version="${TANGLED_REF_NAME}" \ 29 + --label org.opencontainers.image.created="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ 30 + --label org.opencontainers.image.revision="${TANGLED_COMMIT_SHA}" \ 31 + --tag ${IMAGE_REGISTRY}/${TANGLED_REPO_HANDLE}/${TANGLED_REPO_NAME}:${TANGLED_REF_NAME}-amd64 \ 32 + --file ./Dockerfile \ 33 + . 34 + 35 + - name: Create and push manifest 36 + command: | 37 + IMAGE_NAME=${IMAGE_REGISTRY}/${TANGLED_REPO_HANDLE}/${TANGLED_REPO_NAME} 38 + # buildah manifest create ${IMAGE_NAME}:${TANGLED_REF_NAME} 39 + # buildah manifest add ${IMAGE_NAME}:${TANGLED_REF_NAME} ${IMAGE_NAME}:${TANGLED_REF_NAME}-amd64 40 + # buildah manifest add ${IMAGE_NAME}:${TANGLED_REF_NAME} ${IMAGE_NAME}:${TANGLED_REF_NAME}-arm64 41 + buildah manifest push --all ${IMAGE_NAME}:${TANGLED_REF_NAME} docker://${IMAGE_NAME}:${TANGLED_REF_NAME} 42 + buildah manifest push --all ${IMAGE_NAME}:${TANGLED_REF_NAME} docker://${IMAGE_NAME}:latest
+42
.tangled/workflows/release-arm64.yml
··· 1 + when: 2 + - event: ["push"] 3 + branch: ["main"] 4 + tag: ["v*"] 5 + 6 + engine: kubernetes 7 + image: quay.io/buildah/stable:latest 8 + architecture: arm64 9 + 10 + environment: 11 + IMAGE_REGISTRY: atcr.io 12 + 13 + steps: 14 + - name: Login to registry 15 + command: | 16 + echo "${IMAGE_NAME}" 17 + printenv 18 + echo "${APP_PASSWORD}" | buildah login \ 19 + -u "${TANGLED_REPO_HANDLE}" \ 20 + --password-stdin \ 21 + ${IMAGE_REGISTRY} 22 + 23 + - name: Build arm64 image 24 + command: | 25 + buildah bud \ 26 + --arch arm64 \ 27 + --build-arg TARGETARCH=arm64 \ 28 + --label org.opencontainers.image.version="${TANGLED_REF_NAME}" \ 29 + --label org.opencontainers.image.created="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ 30 + --label org.opencontainers.image.revision="${TANGLED_COMMIT_SHA}" \ 31 + --tag ${IMAGE_REGISTRY}/${TANGLED_REPO_HANDLE}/${TANGLED_REPO_NAME}:${TANGLED_REF_NAME}-arm64 \ 32 + --file ./Dockerfile \ 33 + . 34 + 35 + - name: Create and push manifest 36 + command: | 37 + IMAGE_NAME=${IMAGE_REGISTRY}/${TANGLED_REPO_HANDLE}/${TANGLED_REPO_NAME} 38 + # buildah manifest create ${IMAGE_NAME}:${TANGLED_REF_NAME} 39 + # buildah manifest add ${IMAGE_NAME}:${TANGLED_REF_NAME} ${IMAGE_NAME}:${TANGLED_REF_NAME}-amd64 40 + # buildah manifest add ${IMAGE_NAME}:${TANGLED_REF_NAME} ${IMAGE_NAME}:${TANGLED_REF_NAME}-arm64 41 + buildah manifest push --all ${IMAGE_NAME}:${TANGLED_REF_NAME} docker://${IMAGE_NAME}:${TANGLED_REF_NAME} 42 + buildah manifest push --all ${IMAGE_NAME}:${TANGLED_REF_NAME} docker://${IMAGE_NAME}:latest
-56
.tangled/workflows/release.yml
··· 1 - when: 2 - - event: ["push"] 3 - branch: ["main"] 4 - tag: ["v*"] 5 - 6 - engine: kubernetes 7 - image: quay.io/buildah/stable:latest 8 - architecture: amd64 9 - 10 - environment: 11 - IMAGE_REGISTRY: atcr.io 12 - IMAGE_NAME: ${IMAGE_REGISTRY}/${TANGLED_REPO_HANDLE}/${TANGLED_REPO_NAME} 13 - 14 - steps: 15 - - name: Login to registry 16 - command: | 17 - echo "${APP_PASSWORD}" | buildah login \ 18 - -u "${TANGLED_REPO_HANDLE}" \ 19 - --password-stdin \ 20 - ${IMAGE_REGISTRY} 21 - 22 - - name: Build amd64 image 23 - command: | 24 - buildah bud \ 25 - --arch amd64 \ 26 - --build-arg TARGETARCH=amd64 \ 27 - --build-arg VERSION=${TANGLED_REF_NAME} \ 28 - --build-arg CREATED=$(date -u +%Y-%m-%dT%H:%M:%SZ) \ 29 - --build-arg REVISION=${TANGLED_COMMIT_SHA} \ 30 - --build-arg TANGLED_REPO_DID=${TANGLED_REPO_DID} \ 31 - --build-arg TANGLED_REPO_NAME=${TANGLED_REPO_NAME} \ 32 - --tag ${IMAGE_NAME}:${TANGLED_REF_NAME}-amd64 \ 33 - --file ./Dockerfile \ 34 - . 35 - 36 - - name: Build arm64 image 37 - command: | 38 - buildah bud \ 39 - --arch arm64 \ 40 - --build-arg TARGETARCH=arm64 \ 41 - --build-arg VERSION=${TANGLED_REF_NAME} \ 42 - --build-arg CREATED=$(date -u +%Y-%m-%dT%H:%M:%SZ) \ 43 - --build-arg REVISION=${TANGLED_COMMIT_SHA} \ 44 - --build-arg TANGLED_REPO_DID=${TANGLED_REPO_DID} \ 45 - --build-arg TANGLED_REPO_NAME=${TANGLED_REPO_NAME} \ 46 - --tag ${IMAGE_NAME}:${TANGLED_REF_NAME}-arm64 \ 47 - --file ./Dockerfile \ 48 - . 49 - 50 - - name: Create and push manifest 51 - command: | 52 - buildah manifest create ${IMAGE_NAME}:${TANGLED_REF_NAME} 53 - buildah manifest add ${IMAGE_NAME}:${TANGLED_REF_NAME} ${IMAGE_NAME}:${TANGLED_REF_NAME}-amd64 54 - buildah manifest add ${IMAGE_NAME}:${TANGLED_REF_NAME} ${IMAGE_NAME}:${TANGLED_REF_NAME}-arm64 55 - buildah manifest push --all ${IMAGE_NAME}:${TANGLED_REF_NAME} docker://${IMAGE_NAME}:${TANGLED_REF_NAME} 56 - buildah manifest push --all ${IMAGE_NAME}:${TANGLED_REF_NAME} docker://${IMAGE_NAME}:latest
+6 -10
Dockerfile
··· 11 11 12 12 FROM alpine:3.20 13 13 14 - ARG VERSION=dev 15 - ARG CREATED 16 - ARG REVISION 17 - ARG TANGLED_REPO_DID 18 - ARG TANGLED_REPO_NAME 19 - 14 + # Static labels 20 15 LABEL org.opencontainers.image.title="git-summarizer" \ 21 16 org.opencontainers.image.description="AI-powered git change summarizer using agentic tool-calling with self-hosted LLMs" \ 22 - org.opencontainers.image.version="${VERSION}" \ 23 - org.opencontainers.image.created="${CREATED}" \ 24 - org.opencontainers.image.revision="${REVISION}" \ 25 17 org.opencontainers.image.licenses="MIT" \ 26 - org.opencontainers.image.source="https://tangled.sh/${TANGLED_REPO_DID}/${TANGLED_REPO_NAME}" 18 + org.opencontainers.image.authors="Evan Jarrett" \ 19 + org.opencontainers.image.source="https://tangled.org/evan.jarrett.net/git-summarize" \ 20 + org.opencontainers.image.documentation="https://tangled.org/evan.jarrett.net/git-summarize" 21 + 22 + # Dynamic labels are passed via --label flags at build time 27 23 28 24 RUN apk add --no-cache ca-certificates 29 25
+33 -5
Makefile
··· 1 - .PHONY: build run docker test clean 1 + .PHONY: build run docker docker-run docker-build docker-build-local setup-buildx test test-bluesky clean 2 + 3 + # Container tool and image configuration 4 + CONTAINER_TOOL ?= docker 5 + IMG ?= atcr.io/evan.jarrett.net/git-summarizer:latest 2 6 3 7 # Build binary 4 8 build: ··· 9 13 run: build 10 14 ./git-summarizer 11 15 12 - # Build docker image 16 + # Build docker image (legacy, use docker-build-local or docker-build instead) 13 17 docker: 14 - docker build -t git-summarizer:latest . 18 + $(CONTAINER_TOOL) build -t $(IMG) . 15 19 16 20 # Run docker locally 17 21 docker-run: 18 - docker run --network=host \ 22 + $(CONTAINER_TOOL) run --network=host \ 19 23 -e LLAMA_URL=https://llama.j5t.io \ 20 24 -e LLAMA_MODEL=qwen3-coder-30b \ 21 - git-summarizer:latest 25 + $(IMG) 26 + 27 + # Build and push multi-arch docker image (amd64 + arm64) 28 + docker-build: setup-buildx 29 + $(CONTAINER_TOOL) buildx build \ 30 + --builder git-summarizer-builder \ 31 + --platform=linux/amd64,linux/arm64 \ 32 + --push \ 33 + --tag $(IMG) \ 34 + . 35 + 36 + # Build docker image for local arch only (no push) 37 + docker-build-local: 38 + $(CONTAINER_TOOL) build -t $(IMG) . 39 + 40 + # Set up buildx builder for multi-arch builds 41 + setup-buildx: 42 + @echo "Setting up git-summarizer-builder..." 43 + -$(CONTAINER_TOOL) buildx rm git-summarizer-builder 2>/dev/null || true 44 + $(CONTAINER_TOOL) buildx create --name git-summarizer-builder \ 45 + --driver docker-container \ 46 + --driver-opt network=host \ 47 + --config /dev/stdin <<< 'debug = true' || true 48 + $(CONTAINER_TOOL) buildx inspect --bootstrap git-summarizer-builder 49 + @echo "✓ Builder setup complete!" 22 50 23 51 # Test with a public repo 24 52 test: