merge: integrate origin/main to resolve CI (matrix_send_ctx)
Merge main into feat/exec-agent to pick up ba1ab6e which added
matrix_send_ctx to lib/env.sh and action/action-agent.sh. Without
this merge, CI smoke test fails on the PR merge commit.
Re-applied exec changes on top of main:
- .env.example, AGENTS.md, bin/disinto, lib/matrix_listener.sh
- .woodpecker/agent-smoke.sh: exec scripts added to checks
This commit is contained in:
commit
18cea8cad5
2 changed files with 144 additions and 31 deletions
|
|
@ -82,7 +82,7 @@ while IFS= read -r -d '' f; do
|
||||||
printf 'FAIL [syntax] %s\n' "$f"
|
printf 'FAIL [syntax] %s\n' "$f"
|
||||||
FAILED=1
|
FAILED=1
|
||||||
fi
|
fi
|
||||||
done < <(find dev gardener review planner supervisor lib vault action -name "*.sh" -print0 2>/dev/null)
|
done < <(find dev gardener review planner supervisor lib vault action exec -name "*.sh" -print0 2>/dev/null)
|
||||||
echo "syntax check done"
|
echo "syntax check done"
|
||||||
|
|
||||||
# ── 2. Function-resolution check ─────────────────────────────────────────────
|
# ── 2. Function-resolution check ─────────────────────────────────────────────
|
||||||
|
|
@ -213,6 +213,9 @@ check_script action/action-agent.sh dev/phase-handler.sh
|
||||||
check_script supervisor/supervisor-run.sh
|
check_script supervisor/supervisor-run.sh
|
||||||
check_script supervisor/preflight.sh
|
check_script supervisor/preflight.sh
|
||||||
check_script predictor/predictor-run.sh
|
check_script predictor/predictor-run.sh
|
||||||
|
check_script exec/exec-session.sh
|
||||||
|
check_script exec/exec-inject.sh
|
||||||
|
check_script exec/exec-briefing.sh
|
||||||
|
|
||||||
echo "function resolution check done"
|
echo "function resolution check done"
|
||||||
|
|
||||||
|
|
|
||||||
170
bin/disinto
170
bin/disinto
|
|
@ -155,7 +155,8 @@ generate_compose() {
|
||||||
|
|
||||||
cat > "$compose_file" <<'COMPOSEEOF'
|
cat > "$compose_file" <<'COMPOSEEOF'
|
||||||
# docker-compose.yml — generated by disinto init
|
# docker-compose.yml — generated by disinto init
|
||||||
# Brings up Forgejo, Woodpecker, Dendrite (Matrix), and the agent runtime.
|
# Brings up Forgejo, Woodpecker, and the agent runtime.
|
||||||
|
# Dendrite (Matrix) is added only when init is called with --matrix.
|
||||||
|
|
||||||
services:
|
services:
|
||||||
forgejo:
|
forgejo:
|
||||||
|
|
@ -175,7 +176,7 @@ services:
|
||||||
- disinto-net
|
- disinto-net
|
||||||
|
|
||||||
woodpecker:
|
woodpecker:
|
||||||
image: woodpeckerci/woodpecker-server:latest
|
image: woodpeckerci/woodpecker-server:v3
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
security_opt:
|
security_opt:
|
||||||
- apparmor=unconfined
|
- apparmor=unconfined
|
||||||
|
|
@ -198,7 +199,7 @@ services:
|
||||||
- disinto-net
|
- disinto-net
|
||||||
|
|
||||||
woodpecker-agent:
|
woodpecker-agent:
|
||||||
image: woodpeckerci/woodpecker-agent:latest
|
image: woodpeckerci/woodpecker-agent:v3
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
security_opt:
|
security_opt:
|
||||||
- apparmor=unconfined
|
- apparmor=unconfined
|
||||||
|
|
@ -213,16 +214,6 @@ services:
|
||||||
networks:
|
networks:
|
||||||
- disinto-net
|
- disinto-net
|
||||||
|
|
||||||
dendrite:
|
|
||||||
image: matrixdotorg/dendrite-monolith:latest
|
|
||||||
restart: unless-stopped
|
|
||||||
volumes:
|
|
||||||
- dendrite-data:/etc/dendrite
|
|
||||||
environment:
|
|
||||||
DENDRITE_DOMAIN: disinto.local
|
|
||||||
networks:
|
|
||||||
- disinto-net
|
|
||||||
|
|
||||||
agents:
|
agents:
|
||||||
build: ./docker/agents
|
build: ./docker/agents
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
@ -238,21 +229,18 @@ services:
|
||||||
environment:
|
environment:
|
||||||
FORGE_URL: http://forgejo:3000
|
FORGE_URL: http://forgejo:3000
|
||||||
WOODPECKER_SERVER: http://woodpecker:8000
|
WOODPECKER_SERVER: http://woodpecker:8000
|
||||||
MATRIX_HOMESERVER: http://dendrite:8008
|
|
||||||
DISINTO_CONTAINER: "1"
|
DISINTO_CONTAINER: "1"
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
depends_on:
|
depends_on:
|
||||||
- forgejo
|
- forgejo
|
||||||
- woodpecker
|
- woodpecker
|
||||||
- dendrite
|
|
||||||
networks:
|
networks:
|
||||||
- disinto-net
|
- disinto-net
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
forgejo-data:
|
forgejo-data:
|
||||||
woodpecker-data:
|
woodpecker-data:
|
||||||
dendrite-data:
|
|
||||||
agent-data:
|
agent-data:
|
||||||
project-repos:
|
project-repos:
|
||||||
|
|
||||||
|
|
@ -284,6 +272,70 @@ COMPOSEEOF
|
||||||
echo "Created: ${compose_file}"
|
echo "Created: ${compose_file}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Append Dendrite (Matrix) service to docker-compose.yml and generate config.
|
||||||
|
# Called only when --matrix flag is passed to init.
|
||||||
|
append_dendrite_compose() {
|
||||||
|
local compose_file="${FACTORY_ROOT}/docker-compose.yml"
|
||||||
|
local dendrite_config_dir="${FACTORY_ROOT}/docker/dendrite"
|
||||||
|
local dendrite_yaml="${dendrite_config_dir}/dendrite.yaml"
|
||||||
|
|
||||||
|
mkdir -p "$dendrite_config_dir"
|
||||||
|
|
||||||
|
# Generate a minimal dendrite.yaml
|
||||||
|
cat > "$dendrite_yaml" <<'DENDRITECFG'
|
||||||
|
# dendrite.yaml — generated by disinto init --matrix
|
||||||
|
version: 2
|
||||||
|
global:
|
||||||
|
server_name: disinto.local
|
||||||
|
private_key: matrix_key.pem
|
||||||
|
database:
|
||||||
|
connection_string: file:dendrite.db
|
||||||
|
cache:
|
||||||
|
max_size_estimated: 512mb
|
||||||
|
jetstream:
|
||||||
|
storage_path: /etc/dendrite/jetstream
|
||||||
|
client_api:
|
||||||
|
registration_disabled: true
|
||||||
|
DENDRITECFG
|
||||||
|
echo "Created: ${dendrite_yaml}"
|
||||||
|
|
||||||
|
# Append dendrite service before the volumes: section
|
||||||
|
python3 -c "
|
||||||
|
import sys, pathlib
|
||||||
|
p = pathlib.Path(sys.argv[1])
|
||||||
|
text = p.read_text()
|
||||||
|
dendrite_service = '''
|
||||||
|
dendrite:
|
||||||
|
image: matrixdotorg/dendrite-monolith:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- dendrite-data:/etc/dendrite
|
||||||
|
- ./docker/dendrite/dendrite.yaml:/etc/dendrite/dendrite.yaml:ro
|
||||||
|
environment:
|
||||||
|
DENDRITE_DOMAIN: disinto.local
|
||||||
|
networks:
|
||||||
|
- disinto-net
|
||||||
|
'''
|
||||||
|
# Insert dendrite service before 'volumes:' line
|
||||||
|
text = text.replace('\nvolumes:\n', dendrite_service + '\nvolumes:\n', 1)
|
||||||
|
# Add dendrite-data volume
|
||||||
|
text = text.replace(' agent-data:', ' dendrite-data:\n agent-data:')
|
||||||
|
# Add MATRIX_HOMESERVER env var to agents service
|
||||||
|
text = text.replace(
|
||||||
|
' DISINTO_CONTAINER: \"1\"',
|
||||||
|
' MATRIX_HOMESERVER: http://dendrite:8008\n DISINTO_CONTAINER: \"1\"'
|
||||||
|
)
|
||||||
|
# Add dendrite dependency to agents service
|
||||||
|
text = text.replace(
|
||||||
|
' - woodpecker\n networks:',
|
||||||
|
' - woodpecker\n - dendrite\n networks:'
|
||||||
|
)
|
||||||
|
p.write_text(text)
|
||||||
|
" "$compose_file"
|
||||||
|
|
||||||
|
echo "Updated: ${compose_file} (added Dendrite service)"
|
||||||
|
}
|
||||||
|
|
||||||
# Generate docker/agents/ files if they don't already exist.
|
# Generate docker/agents/ files if they don't already exist.
|
||||||
generate_agent_docker() {
|
generate_agent_docker() {
|
||||||
local docker_dir="${FACTORY_ROOT}/docker/agents"
|
local docker_dir="${FACTORY_ROOT}/docker/agents"
|
||||||
|
|
@ -602,19 +654,58 @@ setup_forge() {
|
||||||
# Push local clone to the Forgejo remote.
|
# Push local clone to the Forgejo remote.
|
||||||
push_to_forge() {
|
push_to_forge() {
|
||||||
local repo_root="$1" forge_url="$2" repo_slug="$3"
|
local repo_root="$1" forge_url="$2" repo_slug="$3"
|
||||||
local remote_url="${forge_url}/${repo_slug}.git"
|
|
||||||
|
|
||||||
|
# Build authenticated remote URL: http://dev-bot:<token>@host:port/org/repo.git
|
||||||
|
if [ -z "${FORGE_TOKEN:-}" ]; then
|
||||||
|
echo "Error: FORGE_TOKEN not set — cannot push to Forgejo" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
local auth_url
|
||||||
|
auth_url=$(printf '%s' "$forge_url" | sed "s|://|://dev-bot:${FORGE_TOKEN}@|")
|
||||||
|
local remote_url="${auth_url}/${repo_slug}.git"
|
||||||
|
# Display URL without token
|
||||||
|
local display_url="${forge_url}/${repo_slug}.git"
|
||||||
|
|
||||||
|
# Always set the remote URL to ensure credentials are current
|
||||||
if git -C "$repo_root" remote get-url forgejo >/dev/null 2>&1; then
|
if git -C "$repo_root" remote get-url forgejo >/dev/null 2>&1; then
|
||||||
echo "Remote: forgejo (already configured)"
|
git -C "$repo_root" remote set-url forgejo "$remote_url"
|
||||||
else
|
else
|
||||||
git -C "$repo_root" remote add forgejo "$remote_url" 2>/dev/null || \
|
git -C "$repo_root" remote add forgejo "$remote_url"
|
||||||
git -C "$repo_root" remote set-url forgejo "$remote_url"
|
fi
|
||||||
echo "Remote: forgejo -> ${remote_url}"
|
echo "Remote: forgejo -> ${display_url}"
|
||||||
|
|
||||||
|
# Skip push if local repo has no commits (e.g. cloned from empty Forgejo repo)
|
||||||
|
if ! git -C "$repo_root" rev-parse HEAD >/dev/null 2>&1; then
|
||||||
|
echo "Push: skipped (local repo has no commits)"
|
||||||
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Push all branches
|
# Push all branches and tags
|
||||||
git -C "$repo_root" push forgejo --all 2>/dev/null || true
|
echo "Pushing: branches to forgejo"
|
||||||
git -C "$repo_root" push forgejo --tags 2>/dev/null || true
|
if ! git -C "$repo_root" push forgejo --all 2>&1; then
|
||||||
|
echo "Error: failed to push branches to Forgejo" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo "Pushing: tags to forgejo"
|
||||||
|
if ! git -C "$repo_root" push forgejo --tags 2>&1; then
|
||||||
|
echo "Error: failed to push tags to Forgejo" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify the repo is no longer empty
|
||||||
|
local repo_info
|
||||||
|
repo_info=$(curl -sf --max-time 10 \
|
||||||
|
-H "Authorization: token ${FORGE_TOKEN}" \
|
||||||
|
"${forge_url}/api/v1/repos/${repo_slug}" 2>/dev/null) || repo_info=""
|
||||||
|
if [ -n "$repo_info" ]; then
|
||||||
|
local is_empty
|
||||||
|
is_empty=$(printf '%s' "$repo_info" | jq -r '.empty // "unknown"')
|
||||||
|
if [ "$is_empty" = "true" ]; then
|
||||||
|
echo "Warning: Forgejo repo still reports empty after push" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo "Verify: repo is not empty (push confirmed)"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Preflight check — verify all factory requirements before proceeding.
|
# Preflight check — verify all factory requirements before proceeding.
|
||||||
|
|
@ -774,8 +865,20 @@ create_labels() {
|
||||||
)
|
)
|
||||||
|
|
||||||
echo "Creating labels on ${repo}..."
|
echo "Creating labels on ${repo}..."
|
||||||
|
|
||||||
|
# Fetch existing labels so we can skip duplicates
|
||||||
|
local existing
|
||||||
|
existing=$(curl -sf \
|
||||||
|
-H "Authorization: token ${FORGE_TOKEN}" \
|
||||||
|
"${api}/labels?limit=50" 2>/dev/null \
|
||||||
|
| grep -o '"name":"[^"]*"' | cut -d'"' -f4) || existing=""
|
||||||
|
|
||||||
local name color
|
local name color
|
||||||
for name in backlog in-progress blocked tech-debt underspecified vision action; do
|
for name in backlog in-progress blocked tech-debt underspecified vision action; do
|
||||||
|
if echo "$existing" | grep -qx "$name"; then
|
||||||
|
echo " . ${name} (already exists)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
color="${labels[$name]}"
|
color="${labels[$name]}"
|
||||||
if curl -sf -X POST \
|
if curl -sf -X POST \
|
||||||
-H "Authorization: token ${FORGE_TOKEN}" \
|
-H "Authorization: token ${FORGE_TOKEN}" \
|
||||||
|
|
@ -784,7 +887,7 @@ create_labels() {
|
||||||
-d "{\"name\":\"${name}\",\"color\":\"${color}\"}" >/dev/null 2>&1; then
|
-d "{\"name\":\"${name}\",\"color\":\"${color}\"}" >/dev/null 2>&1; then
|
||||||
echo " + ${name}"
|
echo " + ${name}"
|
||||||
else
|
else
|
||||||
echo " . ${name} (already exists)"
|
echo " ! ${name} (failed to create)"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
@ -1162,7 +1265,7 @@ disinto_init() {
|
||||||
shift
|
shift
|
||||||
|
|
||||||
# Parse flags
|
# Parse flags
|
||||||
local branch="" repo_root="" ci_id="0" auto_yes=false forge_url_flag="" bare=false
|
local branch="" repo_root="" ci_id="0" auto_yes=false forge_url_flag="" bare=false enable_matrix=false
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--branch) branch="$2"; shift 2 ;;
|
--branch) branch="$2"; shift 2 ;;
|
||||||
|
|
@ -1170,6 +1273,7 @@ disinto_init() {
|
||||||
--ci-id) ci_id="$2"; shift 2 ;;
|
--ci-id) ci_id="$2"; shift 2 ;;
|
||||||
--forge-url) forge_url_flag="$2"; shift 2 ;;
|
--forge-url) forge_url_flag="$2"; shift 2 ;;
|
||||||
--bare) bare=true; shift ;;
|
--bare) bare=true; shift ;;
|
||||||
|
--matrix) enable_matrix=true; shift ;;
|
||||||
--yes) auto_yes=true; shift ;;
|
--yes) auto_yes=true; shift ;;
|
||||||
*) echo "Unknown option: $1" >&2; exit 1 ;;
|
*) echo "Unknown option: $1" >&2; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
|
|
@ -1253,6 +1357,9 @@ p.write_text(text)
|
||||||
forge_port=$(printf '%s' "$forge_url" | sed -E 's|.*:([0-9]+)/?$|\1|')
|
forge_port=$(printf '%s' "$forge_url" | sed -E 's|.*:([0-9]+)/?$|\1|')
|
||||||
forge_port="${forge_port:-3000}"
|
forge_port="${forge_port:-3000}"
|
||||||
generate_compose "$forge_port"
|
generate_compose "$forge_port"
|
||||||
|
if [ "$enable_matrix" = true ]; then
|
||||||
|
append_dendrite_compose
|
||||||
|
fi
|
||||||
generate_agent_docker
|
generate_agent_docker
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -1344,10 +1451,13 @@ p.write_text(text)
|
||||||
echo ""
|
echo ""
|
||||||
echo "── Starting full stack ────────────────────────────────"
|
echo "── Starting full stack ────────────────────────────────"
|
||||||
docker compose -f "${FACTORY_ROOT}/docker-compose.yml" up -d
|
docker compose -f "${FACTORY_ROOT}/docker-compose.yml" up -d
|
||||||
echo "Stack: running (forgejo + woodpecker + dendrite + agents)"
|
if [ "$enable_matrix" = true ]; then
|
||||||
|
echo "Stack: running (forgejo + woodpecker + dendrite + agents)"
|
||||||
# Provision Matrix now that Dendrite is running
|
# Provision Matrix now that Dendrite is running
|
||||||
setup_matrix
|
setup_matrix
|
||||||
|
else
|
||||||
|
echo "Stack: running (forgejo + woodpecker + agents)"
|
||||||
|
fi
|
||||||
|
|
||||||
# Activate repo in Woodpecker now that stack is running
|
# Activate repo in Woodpecker now that stack is running
|
||||||
activate_woodpecker_repo "$forge_repo"
|
activate_woodpecker_repo "$forge_repo"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue