Skip to content

Commit cd5c7d0

Browse files
committed
Added tooling
1 parent 4d87df8 commit cd5c7d0

File tree

7 files changed

+257
-3
lines changed

7 files changed

+257
-3
lines changed

.github/workflows/docker.yaml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: Create Docker Image
2+
on:
3+
release:
4+
types:
5+
- created
6+
7+
workflow_dispatch:
8+
9+
jobs:
10+
build:
11+
name: Build
12+
strategy:
13+
matrix:
14+
arch: [ amd64, arm64 ]
15+
runs-on:
16+
- ${{ matrix.arch == 'amd64' && 'ubuntu-latest' || matrix.arch }}
17+
env:
18+
OS: linux
19+
ARCH: ${{ matrix.arch }}
20+
DOCKER_REPO: ghcr.io/${{ github.repository }}
21+
DOCKER_SOURCE: https://github.com/${{ github.repository }}
22+
outputs:
23+
tag: ${{ steps.build.outputs.tag }}
24+
permissions:
25+
contents: read
26+
packages: write
27+
steps:
28+
- name: Install build tools
29+
run: |
30+
sudo apt -y update
31+
sudo apt -y install build-essential git
32+
git config --global advice.detachedHead false
33+
- name: Checkout
34+
uses: actions/checkout@v4
35+
with:
36+
fetch-depth: 0
37+
- name: Login
38+
uses: docker/login-action@v3
39+
with:
40+
registry: ghcr.io
41+
username: ${{ github.repository_owner }}
42+
password: ${{ secrets.GITHUB_TOKEN }}
43+
- name: Build and Push
44+
id: build
45+
run: |
46+
make docker && make docker-push && make docker-version >> "$GITHUB_OUTPUT"
47+
manifest:
48+
name: Manifest
49+
needs: build
50+
strategy:
51+
matrix:
52+
tag:
53+
- ${{ needs.build.outputs.tag }}
54+
- "latest"
55+
runs-on: ubuntu-latest
56+
permissions:
57+
packages: write
58+
steps:
59+
- name: Login
60+
uses: docker/login-action@v3
61+
with:
62+
registry: ghcr.io
63+
username: ${{ github.repository_owner }}
64+
password: ${{ secrets.GITHUB_TOKEN }}
65+
- name: Create
66+
run: |
67+
docker manifest create ghcr.io/${{ github.repository }}:${{ matrix.tag }} \
68+
--amend ghcr.io/${{ github.repository }}-linux-amd64:${{ needs.build.outputs.tag }} \
69+
--amend ghcr.io/${{ github.repository }}-linux-arm64:${{ needs.build.outputs.tag }}
70+
- name: Annotate
71+
run: |
72+
docker manifest annotate --arch amd64 --os linux \
73+
ghcr.io/${{ github.repository }}:${{ matrix.tag }} \
74+
ghcr.io/${{ github.repository }}-linux-amd64:${{ needs.build.outputs.tag }}
75+
docker manifest annotate --arch arm64 --os linux \
76+
ghcr.io/${{ github.repository }}:${{ matrix.tag }} \
77+
ghcr.io/${{ github.repository }}-linux-arm64:${{ needs.build.outputs.tag }}
78+
- name: Push
79+
run: |
80+
docker manifest push ghcr.io/${{ github.repository }}:${{ matrix.tag }}

Makefile

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Executables
2+
GO ?= $(shell which go 2>/dev/null)
3+
DOCKER ?= $(shell which docker 2>/dev/null)
4+
5+
# Locations
6+
BUILD_DIR ?= build
7+
CMD_DIR := $(wildcard cmd/*)
8+
9+
# VERBOSE=1
10+
ifneq ($(VERBOSE),)
11+
VERBOSE_FLAG = -v
12+
else
13+
VERBOSE_FLAG =
14+
endif
15+
16+
# Set OS and Architecture
17+
ARCH ?= $(shell arch | tr A-Z a-z | sed 's/x86_64/amd64/' | sed 's/i386/amd64/' | sed 's/armv7l/arm/' | sed 's/aarch64/arm64/')
18+
OS ?= $(shell uname | tr A-Z a-z)
19+
VERSION ?= $(shell git describe --tags --always | sed 's/^v//')
20+
21+
# Set build flags
22+
BUILD_MODULE = $(shell cat go.mod | head -1 | cut -d ' ' -f 2)
23+
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitSource=${BUILD_MODULE}
24+
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitTag=$(shell git describe --tags --always)
25+
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitBranch=$(shell git name-rev HEAD --name-only --always)
26+
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitHash=$(shell git rev-parse HEAD)
27+
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GoBuildTime=$(shell date -u '+%Y-%m-%dT%H:%M:%SZ')
28+
BUILD_FLAGS = -ldflags "-s -w ${BUILD_LD_FLAGS}"
29+
30+
# Docker
31+
DOCKER_REPO ?= ghcr.io/mutablelogic/go-llm
32+
DOCKER_SOURCE ?= ${BUILD_MODULE}
33+
DOCKER_TAG = ${DOCKER_REPO}-${OS}-${ARCH}:${VERSION}
34+
35+
###############################################################################
36+
# ALL
37+
38+
.PHONY: all
39+
all: clean build
40+
41+
###############################################################################
42+
# BUILD
43+
44+
# Build the commands in the cmd directory
45+
.PHONY: build
46+
build: tidy $(CMD_DIR)
47+
48+
$(CMD_DIR): go-dep mkdir
49+
@echo Build command $(notdir $@) GOOS=${OS} GOARCH=${ARCH}
50+
@GOOS=${OS} GOARCH=${ARCH} ${GO} build ${BUILD_FLAGS} -o ${BUILD_DIR}/$(notdir $@) ./$@
51+
52+
# Build the docker image
53+
.PHONY: docker
54+
docker: docker-dep
55+
@echo build docker image ${DOCKER_TAG} OS=${OS} ARCH=${ARCH} SOURCE=${DOCKER_SOURCE} VERSION=${VERSION}
56+
@${DOCKER} build \
57+
--tag ${DOCKER_TAG} \
58+
--build-arg ARCH=${ARCH} \
59+
--build-arg OS=${OS} \
60+
--build-arg SOURCE=${DOCKER_SOURCE} \
61+
--build-arg VERSION=${VERSION} \
62+
-f etc/docker/Dockerfile .
63+
64+
# Push docker container
65+
.PHONY: docker-push
66+
docker-push: docker-dep
67+
@echo push docker image: ${DOCKER_TAG}
68+
@${DOCKER} push ${DOCKER_TAG}
69+
70+
# Print out the version
71+
.PHONY: docker-version
72+
docker-version: docker-dep
73+
@echo "tag=${VERSION}"
74+
75+
###############################################################################
76+
# TEST
77+
78+
.PHONY: test
79+
test: unit-test coverage-test
80+
81+
.PHONY: unit-test
82+
unit-test: go-dep
83+
@echo Unit Tests
84+
@${GO} test ${VERBOSE_FLAG} ./pkg/...
85+
86+
.PHONY: coverage-test
87+
coverage-test: go-dep mkdir
88+
@echo Test Coverage
89+
@${GO} test -coverprofile ${BUILD_DIR}/coverprofile.out ./pkg/...
90+
91+
###############################################################################
92+
# CLEAN
93+
94+
.PHONY: tidy
95+
tidy:
96+
@echo Running go mod tidy
97+
@${GO} mod tidy
98+
99+
.PHONY: mkdir
100+
mkdir:
101+
@install -d ${BUILD_DIR}
102+
103+
.PHONY: clean
104+
clean:
105+
@echo Clean
106+
@rm -fr $(BUILD_DIR)
107+
@${GO} clean
108+
109+
###############################################################################
110+
# DEPENDENCIES
111+
112+
.PHONY: go-dep
113+
go-dep:
114+
@test -f "${GO}" && test -x "${GO}" || (echo "Missing go binary" && exit 1)
115+
116+
.PHONY: docker-dep
117+
docker-dep:
118+
@test -f "${DOCKER}" && test -x "${DOCKER}" || (echo "Missing docker binary" && exit 1)

cmd/agent/chat.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func (cmd *ChatCmd) Run(globals *Globals) error {
8888
for _, call := range calls {
8989
names = append(names, call.Name())
9090
}
91-
globals.term.Println("Calling", strings.Join(names, ", "))
91+
globals.term.Println("Calling ", strings.Join(names, ", "))
9292
}
9393
if results, err := globals.toolkit.Run(ctx, calls...); err != nil {
9494
return err

cmd/agent/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func main() {
7171
cli := CLI{}
7272
cmd := kong.Parse(&cli,
7373
kong.Name(execName()),
74-
kong.Description("Agent command line interface"),
74+
kong.Description("LLM agent command line interface"),
7575
kong.UsageOnError(),
7676
kong.ConfigureHelp(kong.HelpOptions{Compact: true}),
7777
kong.Vars{},

etc/docker/Dockerfile

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
ARG OS
2+
ARG ARCH
3+
4+
# Run makefile to build all the commands
5+
FROM --platform=${OS}/${ARCH} golang:latest AS builder
6+
ARG OS
7+
ARG ARCH
8+
WORKDIR /usr/src/app
9+
COPY . .
10+
11+
# Build the server
12+
RUN \
13+
apt update -y && apt upgrade -y && \
14+
OS=${OS} ARCH=${ARCH} make build
15+
16+
# Copy binaries to /usr/local/bin
17+
FROM --platform=${OS}/${ARCH} debian:bookworm-slim
18+
ARG OS
19+
ARG ARCH
20+
ARG SOURCE
21+
COPY --from=builder /usr/src/app/build/* /usr/local/bin/
22+
RUN apt update -y && apt install -y ca-certificates
23+
24+
# Labels
25+
LABEL org.opencontainers.image.source=https://${SOURCE}
26+
27+
# Entrypoint when running the server
28+
ENTRYPOINT [ "/usr/local/bin/agent" ]

go.mod

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@ module github.com/mutablelogic/go-llm
33
go 1.23.5
44

55
require (
6+
github.com/MichaelMure/go-term-text v0.3.1
67
github.com/alecthomas/kong v1.7.0
8+
github.com/djthorpe/go-errors v1.0.3
9+
github.com/fatih/color v1.9.0
710
github.com/mutablelogic/go-client v1.0.10
811
github.com/stretchr/testify v1.10.0
912
golang.org/x/term v0.28.0
1013
)
1114

1215
require (
1316
github.com/davecgh/go-spew v1.1.1 // indirect
14-
github.com/djthorpe/go-errors v1.0.3 // indirect
17+
github.com/mattn/go-colorable v0.1.4 // indirect
18+
github.com/mattn/go-isatty v0.0.11 // indirect
19+
github.com/mattn/go-runewidth v0.0.15 // indirect
1520
github.com/pmezard/go-difflib v1.0.0 // indirect
21+
github.com/rivo/uniseg v0.4.7 // indirect
1622
golang.org/x/sys v0.29.0 // indirect
1723
gopkg.in/yaml.v3 v3.0.1 // indirect
1824
)

go.sum

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,48 @@
1+
github.com/MichaelMure/go-term-text v0.3.1 h1:Kw9kZanyZWiCHOYu9v/8pWEgDQ6UVN9/ix2Vd2zzWf0=
2+
github.com/MichaelMure/go-term-text v0.3.1/go.mod h1:QgVjAEDUnRMlzpS6ky5CGblux7ebeiLnuy9dAaFZu8o=
13
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
24
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
35
github.com/alecthomas/kong v1.7.0 h1:MnT8+5JxFDCvISeI6vgd/mFbAJwueJ/pqQNzZMsiqZE=
46
github.com/alecthomas/kong v1.7.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
57
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
68
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
9+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
710
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
811
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
912
github.com/djthorpe/go-errors v1.0.3 h1:GZeMPkC1mx2vteXLI/gvxZS0Ee9zxzwD1mcYyKU5jD0=
1013
github.com/djthorpe/go-errors v1.0.3/go.mod h1:HtfrZnMd6HsX75Mtbv9Qcnn0BqOrrFArvCaj3RMnZhY=
14+
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
15+
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
1116
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
1217
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
18+
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
19+
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
20+
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
21+
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
22+
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
23+
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
24+
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
25+
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
1326
github.com/mutablelogic/go-client v1.0.10 h1:d4t8irXlGNQrQS/+FoUht+1RnjL9lBaf1e2UasN3ifE=
1427
github.com/mutablelogic/go-client v1.0.10/go.mod h1:XbG8KGo2Efi7PGxXs7rhYxYhLeXL6aCSo6sz0mVchiw=
1528
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1629
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
30+
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
31+
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
32+
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
33+
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
34+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
35+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
1736
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
1837
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
38+
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
39+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
1940
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
2041
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
2142
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
2243
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
2344
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
2445
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
46+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
2547
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
2648
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)