feat(bootstrap): GH_TOKEN-based clone of Scrum4Me + scrum4me-mcp
Fixes the 'no GitHub credentials' deadlock observed in the first
NAS-Docker batch run (2 May 2026): scrum4me-mcp's `wait_for_job`
expects a local clone at `~/Projects/<repo-name>` (convention-fallback
in resolveRepoRoot) but the container had no credentials and no clone.
Agent asked the user how to proceed; turn closed without claim.
Changes:
- `.env.example`: GH_TOKEN (fine-grained PAT, repo+PR scope) and
GH_PRECLONE_REPOS (comma-separated owner/name list, default covers
Scrum4Me + scrum4me-mcp).
- `bin/repo-bootstrap.sh` (new): runs as agent-user; configures git
credential-helper with HTTPS oauth2 token, then clones-or-fetches
each entry in GH_PRECLONE_REPOS into ~/Projects/<name>. Idempotent.
- `bin/entrypoint.sh`: hooks repo-bootstrap before run-agent.sh.
- `Dockerfile`:
- installs `gh` CLI (used for auto_pr `gh pr create`; reads GH_TOKEN
from env directly).
- pre-creates `~agent/Projects` and `~agent/.scrum4me-agent-worktrees`
so directory-ownership is right from the first boot.
- `README.md`: 'Repo bootstrap (clone-on-start)' section + GH_TOKEN
step in the deploy checklist; corrects the obsolete 'no push
credentials' note (agent now pushes feature-branches, gh creates PRs).
Same token covers clone, push and PR-creation — one secret to rotate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
47b1de93db
commit
c090e6c349
5 changed files with 147 additions and 6 deletions
|
|
@ -61,6 +61,15 @@ gosu agent /bin/bash -c 'cat > "${AGENT_STATE_DIR}/state.json"' <<EOF
|
|||
}
|
||||
EOF
|
||||
|
||||
# ----- 3. drop privileges en start daemon-loop --------------------------
|
||||
log "dropping to agent user and starting run-agent.sh"
|
||||
# ----- 3. drop privileges, bootstrap repos, start daemon-loop -----------
|
||||
# repo-bootstrap.sh runs as agent (NOT root) so that the cloned repos
|
||||
# are owned by the agent user and live under ~agent/Projects/<name> —
|
||||
# that is exactly where scrum4me-mcp's resolveRepoRoot looks via its
|
||||
# convention fallback.
|
||||
log "dropping to agent user and bootstrapping repos"
|
||||
gosu agent /opt/agent/bin/repo-bootstrap.sh \
|
||||
>> "${AGENT_LOG_DIR}/repo-bootstrap.log" 2>&1 \
|
||||
|| log "WARN: repo-bootstrap returned non-zero (continuing)"
|
||||
|
||||
log "starting run-agent.sh"
|
||||
exec gosu agent /opt/agent/bin/run-agent.sh
|
||||
|
|
|
|||
68
bin/repo-bootstrap.sh
Normal file
68
bin/repo-bootstrap.sh
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#!/usr/bin/env bash
|
||||
# repo-bootstrap.sh — pre-clone repos into ~agent/Projects so that
|
||||
# scrum4me-mcp's `wait_for_job` finds a working repoRoot via the
|
||||
# convention-fallback `~/Projects/<name>/.git`.
|
||||
#
|
||||
# Idempotent:
|
||||
# - Sets up git credential helper using GH_TOKEN (HTTPS auth)
|
||||
# - For each entry in GH_PRECLONE_REPOS (comma-separated owner/name list):
|
||||
# * If ~/Projects/<name> exists → `git fetch origin --prune`
|
||||
# * Otherwise → fresh `git clone`
|
||||
#
|
||||
# Runs as the agent user (called from entrypoint.sh after `gosu agent …`).
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
source /opt/agent/bin/_lib.sh
|
||||
|
||||
: "${GH_TOKEN:=}"
|
||||
: "${GH_PRECLONE_REPOS:=}"
|
||||
|
||||
if [[ -z "$GH_TOKEN" ]]; then
|
||||
log "GH_TOKEN not set — skipping clone bootstrap. wait_for_job will fail until repos exist."
|
||||
return 0 2>/dev/null || exit 0
|
||||
fi
|
||||
|
||||
if [[ -z "$GH_PRECLONE_REPOS" ]]; then
|
||||
log "GH_PRECLONE_REPOS empty — nothing to clone."
|
||||
return 0 2>/dev/null || exit 0
|
||||
fi
|
||||
|
||||
# ----- 1. configure git credential helper for HTTPS clone/push -----------
|
||||
mkdir -p "$HOME"
|
||||
git config --global credential.helper store
|
||||
CREDS_FILE="$HOME/.git-credentials"
|
||||
if [[ ! -f "$CREDS_FILE" ]] || ! grep -q "oauth2:${GH_TOKEN}@github.com" "$CREDS_FILE" 2>/dev/null; then
|
||||
printf 'https://oauth2:%s@github.com\n' "$GH_TOKEN" > "$CREDS_FILE"
|
||||
chmod 600 "$CREDS_FILE"
|
||||
log "git credentials helper configured at ${CREDS_FILE}"
|
||||
fi
|
||||
|
||||
# Prevent the token from leaking into commit-author of automated commits.
|
||||
git config --global user.name "${GIT_AUTHOR_NAME:-Scrum4Me Agent}"
|
||||
git config --global user.email "${GIT_AUTHOR_EMAIL:-agent@scrum4me.local}"
|
||||
|
||||
# ----- 2. clone-or-fetch each repo --------------------------------------
|
||||
mkdir -p "$HOME/Projects"
|
||||
|
||||
IFS=',' read -ra REPOS <<< "$GH_PRECLONE_REPOS"
|
||||
for repo in "${REPOS[@]}"; do
|
||||
repo=$(echo "$repo" | tr -d '[:space:]')
|
||||
[[ -z "$repo" ]] && continue
|
||||
|
||||
name=$(basename "$repo")
|
||||
target="$HOME/Projects/$name"
|
||||
|
||||
if [[ -d "$target/.git" ]]; then
|
||||
log "fetching ${repo} into ${target}"
|
||||
git -C "$target" fetch origin --prune --quiet \
|
||||
|| log "WARN: fetch failed for ${repo} (continuing)"
|
||||
else
|
||||
log "cloning ${repo} into ${target}"
|
||||
rm -rf "$target"
|
||||
git clone --quiet "https://github.com/${repo}.git" "$target" \
|
||||
|| { log "ERROR: clone failed for ${repo}"; continue; }
|
||||
fi
|
||||
done
|
||||
|
||||
log "repo-bootstrap done"
|
||||
Loading…
Add table
Add a link
Reference in a new issue