Initial scaffold: base agent container image
ci/woodpecker/tag/docker Pipeline failed

This commit is contained in:
2026-06-08 22:52:12 +10:00
parent 6233e7511a
commit 7a86b3b487
6 changed files with 231 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
bin/
+9
View File
@@ -0,0 +1,9 @@
when:
- event: pull_request
steps:
- name: docker-build
image: woodpeckerci/plugin-docker-buildx
settings:
repo: git.unkin.net/unkin/agent-base
dry_run: true
+16
View File
@@ -0,0 +1,16 @@
when:
- event: tag
ref: refs/tags/v*
steps:
- name: docker
image: woodpeckerci/plugin-docker-buildx
settings:
registry: git.unkin.net
repo: git.unkin.net/unkin/agent-base
username: droneci
password:
from_secret: DRONECI_PASSWORD
tags:
- ${CI_COMMIT_TAG}
- latest
+19
View File
@@ -0,0 +1,19 @@
FROM git.unkin.net/unkin/almalinux9-base:latest
RUN dnf install -y \
git \
git-lfs \
jq \
curl \
claude-code \
&& dnf clean all
RUN useradd -m -s /bin/bash agent
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
USER agent
WORKDIR /home/agent
ENTRYPOINT ["/entrypoint.sh"]
+27
View File
@@ -0,0 +1,27 @@
.PHONY: build clean patch minor major
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "0.0.0-dev")
build:
docker build -t git.unkin.net/unkin/agent-base:$(VERSION) .
clean:
docker rmi git.unkin.net/unkin/agent-base:$(VERSION) 2>/dev/null || true
_LATEST := $(shell git tag --sort=-v:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$$' | head -1)
_BASE := $(if $(_LATEST),$(_LATEST),v0.0.0)
_MAJ := $(shell echo $(_BASE) | sed 's/^v//' | cut -d. -f1)
_MIN := $(shell echo $(_BASE) | sed 's/^v//' | cut -d. -f2)
_PAT := $(shell echo $(_BASE) | sed 's/^v//' | cut -d. -f3)
patch:
@NEW=v$(_MAJ).$(_MIN).$(shell expr $(_PAT) + 1); \
git tag $$NEW && echo "Tagged $$NEW" && git push origin $$NEW
minor:
@NEW=v$(_MAJ).$(shell expr $(_MIN) + 1).0; \
git tag $$NEW && echo "Tagged $$NEW" && git push origin $$NEW
major:
@NEW=v$(shell expr $(_MAJ) + 1).0.0; \
git tag $$NEW && echo "Tagged $$NEW" && git push origin $$NEW
+159
View File
@@ -0,0 +1,159 @@
#!/usr/bin/env bash
set -euo pipefail
###############################################################################
# entrypoint.sh - Base entrypoint for forgebot AI agent containers
###############################################################################
# ---------------------------------------------------------------------------
# Required environment variables
# ---------------------------------------------------------------------------
REQUIRED_VARS=(
FORGEBOT_REPO
FORGEBOT_REF
FORGEBOT_COMMAND
FORGEBOT_API_URL
FORGEBOT_TASK_ID
ANTHROPIC_API_KEY
)
for var in "${REQUIRED_VARS[@]}"; do
if [[ -z "${!var:-}" ]]; then
echo "FATAL: required env var $var is not set" >&2
exit 1
fi
done
# ---------------------------------------------------------------------------
# Defaults
# ---------------------------------------------------------------------------
export ANTHROPIC_BASE_URL="${ANTHROPIC_BASE_URL:-https://litellm.k8s.syd1.au.unkin.net}"
export GITEA_URL="${GITEA_URL:-https://git.unkin.net}"
FORGEBOT_MODEL="${FORGEBOT_MODEL:-claude-sonnet-4-20250514}"
# ---------------------------------------------------------------------------
# Helper functions
# ---------------------------------------------------------------------------
# Report task status back to the forgebot API.
# report_status <status> <message>
report_status() {
local status="$1"
local message="$2"
curl -sf -X PATCH \
-H "Content-Type: application/json" \
"${FORGEBOT_API_URL}/tasks/${FORGEBOT_TASK_ID}" \
-d "$(jq -n --arg s "$status" --arg m "$message" '{status: $s, message: $m}')" \
|| echo "WARNING: failed to report status '$status'" >&2
}
# Create a subtask. Reads JSON body from stdin or from the first argument.
# echo '{"kind":"review",...}' | create_subtask
# create_subtask '{"kind":"review",...}'
create_subtask() {
local body
if [[ $# -gt 0 ]]; then
body="$1"
else
body="$(cat)"
fi
curl -sf -X POST \
-H "Content-Type: application/json" \
"${FORGEBOT_API_URL}/tasks" \
-d "$body"
}
# Check the status of a task by ID.
# check_task <task_id>
check_task() {
local task_id="$1"
curl -sf -X GET \
-H "Content-Type: application/json" \
"${FORGEBOT_API_URL}/tasks/${task_id}"
}
# Post a comment on the current task.
# post_comment <message>
post_comment() {
local message="$1"
curl -sf -X POST \
-H "Content-Type: application/json" \
"${FORGEBOT_API_URL}/tasks/${FORGEBOT_TASK_ID}/comment" \
-d "$(jq -n --arg m "$message" '{message: $m}')"
}
# ---------------------------------------------------------------------------
# Clone & checkout
# ---------------------------------------------------------------------------
REPO_DIR="/home/agent/workspace"
echo "Cloning ${FORGEBOT_REPO} ..."
git clone "${GITEA_URL}/${FORGEBOT_REPO}.git" "$REPO_DIR"
cd "$REPO_DIR"
echo "Checking out ref ${FORGEBOT_REF} ..."
git checkout "${FORGEBOT_REF}"
# ---------------------------------------------------------------------------
# Extra tools (optional)
# ---------------------------------------------------------------------------
if [[ -n "${FORGEBOT_EXTRA_TOOLS:-}" ]]; then
echo "Downloading extra tools: ${FORGEBOT_EXTRA_TOOLS}"
mkdir -p /home/agent/bin
export PATH="/home/agent/bin:${PATH}"
IFS=',' read -ra TOOLS <<< "$FORGEBOT_EXTRA_TOOLS"
for tool in "${TOOLS[@]}"; do
tool="$(echo "$tool" | xargs)" # trim whitespace
echo " -> fetching $tool"
curl -sf -o "/home/agent/bin/${tool}" \
"${FORGEBOT_API_URL}/tools/${tool}" \
&& chmod +x "/home/agent/bin/${tool}" \
|| echo "WARNING: failed to download tool '${tool}'" >&2
done
fi
# ---------------------------------------------------------------------------
# Load skill (optional configmap mount)
# ---------------------------------------------------------------------------
SKILL_CONTEXT=""
if [[ -n "${FORGEBOT_SKILL:-}" && -f "/skills/${FORGEBOT_SKILL}/SKILL.md" ]]; then
echo "Loading skill: ${FORGEBOT_SKILL}"
SKILL_CONTEXT="$(cat "/skills/${FORGEBOT_SKILL}/SKILL.md")"
fi
# ---------------------------------------------------------------------------
# Build the prompt
# ---------------------------------------------------------------------------
PROMPT="${FORGEBOT_COMMAND}"
if [[ -n "$SKILL_CONTEXT" ]]; then
PROMPT="$(printf '%s\n\n---\n\n%s' "$SKILL_CONTEXT" "$PROMPT")"
fi
# ---------------------------------------------------------------------------
# Run claude
# ---------------------------------------------------------------------------
report_status "running" "Agent started, executing command"
set +e
RESULT="$(claude \
--model "$FORGEBOT_MODEL" \
--print \
--dangerously-skip-permissions \
<<< "$PROMPT" 2>&1)"
EXIT_CODE=$?
set -e
# ---------------------------------------------------------------------------
# Report result
# ---------------------------------------------------------------------------
if [[ $EXIT_CODE -eq 0 ]]; then
echo "Agent completed successfully."
report_status "completed" "$RESULT"
else
echo "Agent failed with exit code ${EXIT_CODE}." >&2
report_status "failed" "Exit code ${EXIT_CODE}: ${RESULT}"
fi
exit $EXIT_CODE