Merge pull request 'fix: bug: WOODPECKER_REPO_ID not set in agent containers — ci-debug.sh fails to fetch logs, agents see "No logs available" (#599)' (#601) from fix/issue-599 into main
All checks were successful
ci/woodpecker/push/ci Pipeline was successful

This commit is contained in:
dev-qwen 2026-04-10 11:54:12 +00:00
commit e46c367bd5

View file

@ -26,6 +26,46 @@ PROJECT_NAME="${PROJECT_NAME:-project}"
# PRIMARY_BRANCH defaults to main (env.sh may have set it to 'master') # PRIMARY_BRANCH defaults to main (env.sh may have set it to 'master')
PRIMARY_BRANCH="${PRIMARY_BRANCH:-main}" PRIMARY_BRANCH="${PRIMARY_BRANCH:-main}"
# Helper: extract woodpecker_repo_id from a project TOML file
# Returns empty string if not found or file doesn't exist
_get_woodpecker_repo_id() {
local toml_file="$1"
if [ -f "$toml_file" ]; then
python3 -c "
import sys, tomllib
try:
with open(sys.argv[1], 'rb') as f:
cfg = tomllib.load(f)
ci = cfg.get('ci', {})
wp_id = ci.get('woodpecker_repo_id', '0')
print(wp_id)
except Exception:
print('0')
" "$toml_file" 2>/dev/null || echo "0"
else
echo "0"
fi
}
# Find all project TOML files and extract the highest woodpecker_repo_id
# (used for the main agents service which doesn't have a per-project TOML)
_get_primary_woodpecker_repo_id() {
local projects_dir="${FACTORY_ROOT}/projects"
local max_id="0"
for toml in "${projects_dir}"/*.toml; do
[ -f "$toml" ] || continue
local repo_id
repo_id=$(_get_woodpecker_repo_id "$toml")
if [ -n "$repo_id" ] && [ "$repo_id" != "0" ]; then
# Use the first non-zero repo_id found (or highest if multiple)
if [ "$repo_id" -gt "$max_id" ] 2>/dev/null; then
max_id="$repo_id"
fi
fi
done
echo "$max_id"
}
# Parse project TOML for local-model agents and emit compose services. # Parse project TOML for local-model agents and emit compose services.
# Writes service definitions to stdout; caller handles insertion into compose file. # Writes service definitions to stdout; caller handles insertion into compose file.
_generate_local_model_services() { _generate_local_model_services() {
@ -40,6 +80,10 @@ _generate_local_model_services() {
for toml in "${projects_dir}"/*.toml; do for toml in "${projects_dir}"/*.toml; do
[ -f "$toml" ] || continue [ -f "$toml" ] || continue
# Get woodpecker_repo_id for this project
local wp_repo_id
wp_repo_id=$(_get_woodpecker_repo_id "$toml")
# Parse [agents.*] sections using Python - output YAML-compatible format # Parse [agents.*] sections using Python - output YAML-compatible format
while IFS='=' read -r key value; do while IFS='=' read -r key value; do
case "$key" in case "$key" in
@ -90,6 +134,7 @@ _generate_local_model_services() {
DISINTO_CONTAINER: "1" DISINTO_CONTAINER: "1"
PROJECT_REPO_ROOT: /home/agent/repos/${PROJECT_NAME:-project} PROJECT_REPO_ROOT: /home/agent/repos/${PROJECT_NAME:-project}
WOODPECKER_DATA_DIR: /woodpecker-data WOODPECKER_DATA_DIR: /woodpecker-data
WOODPECKER_REPO_ID: "${wp_repo_id}"
FORGE_BOT_USER_${service_name^^}: "${forge_user}" FORGE_BOT_USER_${service_name^^}: "${forge_user}"
POLL_INTERVAL: "${poll_interval_val}" POLL_INTERVAL: "${poll_interval_val}"
depends_on: depends_on:
@ -186,6 +231,10 @@ _generate_compose_impl() {
return 0 return 0
fi fi
# Extract primary woodpecker_repo_id from project TOML files
local wp_repo_id
wp_repo_id=$(_get_primary_woodpecker_repo_id)
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, and the agent runtime. # Brings up Forgejo, Woodpecker, and the agent runtime.
@ -292,6 +341,7 @@ services:
DISINTO_CONTAINER: "1" DISINTO_CONTAINER: "1"
PROJECT_REPO_ROOT: /home/agent/repos/${PROJECT_NAME:-project} PROJECT_REPO_ROOT: /home/agent/repos/${PROJECT_NAME:-project}
WOODPECKER_DATA_DIR: /woodpecker-data WOODPECKER_DATA_DIR: /woodpecker-data
WOODPECKER_REPO_ID: "PLACEHOLDER_WP_REPO_ID"
# IMPORTANT: agents get explicit environment variables (forge tokens, CI tokens, config). # IMPORTANT: agents get explicit environment variables (forge tokens, CI tokens, config).
# Vault-only secrets (GITHUB_TOKEN, CLAWHUB_TOKEN, deploy keys) live in # Vault-only secrets (GITHUB_TOKEN, CLAWHUB_TOKEN, deploy keys) live in
# .env.vault.enc and are NEVER injected here — only the runner # .env.vault.enc and are NEVER injected here — only the runner
@ -394,6 +444,15 @@ COMPOSEEOF
# (Docker Compose cannot resolve it; it's a shell variable, not a .env var) # (Docker Compose cannot resolve it; it's a shell variable, not a .env var)
sed -i "s|\${PROJECT_NAME:-project}|${PROJECT_NAME}|g" "$compose_file" sed -i "s|\${PROJECT_NAME:-project}|${PROJECT_NAME}|g" "$compose_file"
# Patch WOODPECKER_REPO_ID — interpolate at generation time
# (Docker Compose cannot resolve it; it's a shell variable, not a .env var)
if [ -n "$wp_repo_id" ] && [ "$wp_repo_id" != "0" ]; then
sed -i "s|PLACEHOLDER_WP_REPO_ID|${wp_repo_id}|g" "$compose_file"
else
# Default to empty if no repo_id found (agents will handle gracefully)
sed -i "s|PLACEHOLDER_WP_REPO_ID||g" "$compose_file"
fi
# Patch the forgejo port mapping into the file if non-default # Patch the forgejo port mapping into the file if non-default
if [ "$forge_port" != "3000" ]; then if [ "$forge_port" != "3000" ]; then
# Add port mapping to forgejo service so it's reachable from host during init # Add port mapping to forgejo service so it's reachable from host during init