agents: per-agent Gitea identity — each agent uses its own token
Drop the shared AGENT_TOKEN as the primary credential; every agent now acts as its own Gitea user (TOKEN_PM for @pm, TOKEN_OPS for @ops, …) for API calls, delegation/autopilot trigger comments, and PR merges. - agent.yml: Run-agent step injects SELF_TOKEN — a ternary selecting the running agent's own token by name, falling back to AGENT_TOKEN for repos not yet migrated to per-agent tokens (e.g. homelab). Only that one token enters the agent process, so no agent can act as another. The gitea-api / gitea-admin skill-setup steps no longer carry a token (they only write docs). - Gate: trust the agent roster (pm/junior/senior/lead/qa/ops) as comment authors so an agent's own delegation/autopilot trigger comment (posted with its PAT, no 🤖 prefix) fires the next run. @ops added to the mention set. - publish.sh: TOK = agent identity (comments/replies); new TTOK = trigger/merge token (agent PAT, else AGENT_TOKEN fallback) for delegation, autopilot @qa triggers, and PR merges that must fire downstream workflows. - skill-gitea-api.sh / skill-gitea-admin.sh / run-agent.sh: AGENT_TOKEN/ TOKEN_OPS → SELF_TOKEN in the emitted skill docs and env contract. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
e53e5caf8c
commit
06f1924441
@@ -2,7 +2,7 @@
|
||||
# Publish — PR (dev agents) or comment (pm/qa), always reply in the issue.
|
||||
#
|
||||
# Required env (provided by the workflow step):
|
||||
# GT AGENT_TOKEN TOKEN_PM TOKEN_SENIOR TOKEN_JUNIOR TOKEN_LEAD TOKEN_QA
|
||||
# GT TOKEN_PM TOKEN_SENIOR TOKEN_JUNIOR TOKEN_LEAD TOKEN_QA
|
||||
# NAME MODE NUM TITLE BRANCH NEW GITHUB_SERVER_URL GITHUB_REPOSITORY
|
||||
# IS_PR AUTOPILOT ISSNUM (autopilot: @qa label-gated merge/halt + auto-trigger @qa on a fresh PR)
|
||||
set +e # publish is best-effort: a grep-no-match / curl non-zero must NOT kill the step
|
||||
@@ -12,6 +12,11 @@ case "$NAME" in
|
||||
lead) TOK="$TOKEN_LEAD";; qa) TOK="$TOKEN_QA";; ops) TOK="$TOKEN_OPS";; *) TOK="";;
|
||||
esac
|
||||
[ -z "$TOK" ] && TOK="$GT"
|
||||
# Trigger token: comments that must FIRE the next workflow (delegation, autopilot) and PR merges
|
||||
# cannot use the built-in GITEA_TOKEN (Gitea won't start new runs from it). Use the agent's own PAT
|
||||
# when it has one; otherwise fall back to AGENT_TOKEN (repos without per-agent tokens, e.g. homelab).
|
||||
TTOK="$TOK"
|
||||
{ [ -z "$TTOK" ] || [ "$TTOK" = "$GT" ]; } && TTOK="${AGENT_TOKEN:-}"
|
||||
git config user.name "$NAME"
|
||||
git config user.email "$NAME@ffaerber.duckdns.org"
|
||||
API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}"
|
||||
@@ -120,11 +125,11 @@ if [ "$MODE" != "pr" ]; then
|
||||
echo "MERGE_PR marker but this run is not on a PR thread — skipping merge"
|
||||
else
|
||||
echo "@qa autopilot: merging PR #$NUM (origin issue #${ISSNUM:-$NUM})"
|
||||
# Merge with AGENT_TOKEN (a PAT) — NOT the built-in Actions token — so the resulting push to
|
||||
# Merge with TOK (a PAT) — NOT the built-in Actions token — so the resulting push to
|
||||
# main TRIGGERS downstream workflows (e.g. deploy). A merge made with the built-in GITEA_TOKEN
|
||||
# does not fire new runs (loop-prevention), which silently skips the deploy. Fall back to the
|
||||
# agent's own token only if AGENT_TOKEN isn't set (then the deploy would need a manual run).
|
||||
mtok="${AGENT_TOKEN:-$TOK}"
|
||||
# agent's own token only if TOK isn't set (then the deploy would need a manual run).
|
||||
mtok="$TTOK"
|
||||
mc=$(curl -sS -o /tmp/merge_resp.txt -w '%{http_code}' -X POST \
|
||||
-H "Authorization: token $mtok" -H "Content-Type: application/json" \
|
||||
"$API/pulls/$NUM/merge" -d '{"Do":"merge"}')
|
||||
@@ -164,7 +169,7 @@ if [ "$MODE" != "pr" ]; then
|
||||
else
|
||||
n=$((prior + 1))
|
||||
echo "@qa autopilot: bounce $n/3 -> @$target"
|
||||
curl -sS -X POST -H "Authorization: token $AGENT_TOKEN" -H "Content-Type: application/json" \
|
||||
curl -sS -X POST -H "Authorization: token $TTOK" -H "Content-Type: application/json" \
|
||||
"$API/issues/$NUM/comments" \
|
||||
-d "$(jq -nc --arg b "@$target please address @qa's feedback above and update this PR (autopilot fix attempt $n/3)." '{body:$b}')" \
|
||||
-w '\nbounce -> HTTP %{http_code}\n' || true
|
||||
@@ -178,17 +183,17 @@ if [ "$MODE" != "pr" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Auto-delegate: if the plan names a teammate, trigger them via AGENT_TOKEN (a PAT, so it
|
||||
# Auto-delegate: if the plan names a teammate, trigger them via TOK (a PAT, so it
|
||||
# fires a new workflow run — the built-in token cannot). Never targets @pm or self, so the
|
||||
# chain always terminates at a dev. The '🤖' guard on the trigger stops status-comment loops.
|
||||
if [ -n "$AGENT_TOKEN" ]; then
|
||||
if [ -n "$TTOK" ]; then
|
||||
# Only delegate on an explicit "DELEGATE: @<agent>" line — never on a prose mention,
|
||||
# so an agent that is asking the maintainer a question does not hand off prematurely.
|
||||
target=$(grep -oiE 'DELEGATE:[[:space:]]*@(junior|senior|lead|qa)' /tmp/agent_out.md 2>/dev/null \
|
||||
| head -1 | grep -oiE '(junior|senior|lead|qa)' | tr '[:upper:]' '[:lower:]')
|
||||
if [ -n "$target" ] && [ "$target" != "$NAME" ]; then
|
||||
echo "auto-delegating to @$target"
|
||||
curl -sS -X POST -H "Authorization: token $AGENT_TOKEN" -H "Content-Type: application/json" \
|
||||
curl -sS -X POST -H "Authorization: token $TTOK" -H "Content-Type: application/json" \
|
||||
"$API/issues/$NUM/comments" \
|
||||
-d "$(jq -nc --arg b "@$target please proceed with issue #$NUM per the plan above (delegated by $NAME)." '{body:$b}')" \
|
||||
-w '\ndelegate -> HTTP %{http_code}\n' || true
|
||||
@@ -272,13 +277,13 @@ prpost() {
|
||||
|
||||
if [ "$NEW" = "true" ]; then
|
||||
prpost "$prnum" "$(printf '🤖 **@%s** — ✅ PR ready for review — @ffaerber please review & merge:\n- %s%s' "$NAME" "$url" "$activity")"
|
||||
# AUTOPILOT: hand the fresh PR to @qa automatically (via AGENT_TOKEN, so it fires a new run).
|
||||
# AUTOPILOT: hand the fresh PR to @qa automatically (via TOK, so it fires a new run).
|
||||
# @qa then verifies and — if green — merges + closes via its MERGE_PR marker. The comment lands
|
||||
# on the PR thread ($prnum) so the next run resolves the origin issue's label from the branch
|
||||
# name. The '🤖' guard on the trigger gate stops status-comment loops.
|
||||
if [ "$AUTOPILOT" = "true" ] && [ -n "$AGENT_TOKEN" ] && [ -n "$prnum" ]; then
|
||||
if [ "$AUTOPILOT" = "true" ] && [ -n "$TTOK" ] && [ -n "$prnum" ]; then
|
||||
echo "autopilot: auto-triggering @qa to review PR #$prnum"
|
||||
curl -sS -X POST -H "Authorization: token $AGENT_TOKEN" -H "Content-Type: application/json" \
|
||||
curl -sS -X POST -H "Authorization: token $TTOK" -H "Content-Type: application/json" \
|
||||
"$API/issues/$prnum/comments" \
|
||||
-d "$(jq -nc --arg b "@qa please verify this PR (autopilot: issue #$NUM is labeled autopilot). Merge it if correct, or bounce it back to the dev with exactly what needs fixing." '{body:$b}')" \
|
||||
-w '\ntrigger-qa -> HTTP %{http_code}\n' || true
|
||||
@@ -288,11 +293,11 @@ else
|
||||
# repeat the full write-up in the comment (the reasoning trail below shows what this run did).
|
||||
prpost "$prnum" "$(printf '🤖 **@%s** — pushed an update to the PR:\n- %s%s' "$NAME" "$url" "$activity")"
|
||||
# AUTOPILOT: after a dev pushes a fix (e.g. following a @qa bounce), hand back to @qa to re-verify.
|
||||
if [ "$AUTOPILOT" = "true" ] && [ -n "$AGENT_TOKEN" ] && [ -n "$prnum" ]; then
|
||||
if [ "$AUTOPILOT" = "true" ] && [ -n "$TTOK" ] && [ -n "$prnum" ]; then
|
||||
case "$NAME" in
|
||||
junior|senior|lead)
|
||||
echo "autopilot: dev pushed a fix — re-triggering @qa to re-verify PR #$prnum"
|
||||
curl -sS -X POST -H "Authorization: token $AGENT_TOKEN" -H "Content-Type: application/json" \
|
||||
curl -sS -X POST -H "Authorization: token $TTOK" -H "Content-Type: application/json" \
|
||||
"$API/issues/$prnum/comments" \
|
||||
-d "$(jq -nc --arg b "@qa please re-verify this PR (autopilot). Merge it if now correct, or bounce it back with exactly what still needs fixing." '{body:$b}')" \
|
||||
-w '\ntrigger-qa -> HTTP %{http_code}\n' || true
|
||||
|
||||
Reference in New Issue
Block a user