Skip to content

🕊️ Ciel Bot

🕊️ Ciel Bot #462

Workflow file for this run

# nullvariant-ciel[bot] - The sky messenger
# "まあまあ、ほどほどに。"
name: 🕊️ Ciel Bot
permissions: {}
on:
# Ciel mediates AFTER other bots finish, not on PR events directly.
# workflow_run triggers when the specified workflows complete.
workflow_run:
workflows:
- "👮 Justice Bot"
- "🦥 Slow Bot"
- "🐰 Mimi Bot"
- "👧 Luna Bot"
- "🐗 Blaze Bot"
types: [completed]
workflow_dispatch:
inputs:
message:
description: 'What should Ciel whisper? (optional)'
required: false
default: 'Peace and balance...'
jobs:
mediation:
name: 🕊️ Zoo Mediation
runs-on: ubuntu-latest
if: >
github.event_name == 'workflow_run' &&
github.event.workflow_run.event == 'pull_request_target' &&
github.event.workflow_run.pull_requests[0].number > 0
env:
GH_REPO: ${{ github.repository }}
permissions:
contents: read
pull-requests: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: audit
- name: 🔑 Get App Token
id: app-token
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2
with:
app_id: ${{ secrets.CIEL_BOT_APP_ID }}
private_key: ${{ secrets.CIEL_BOT_PRIVATE_KEY }}
# SECURITY: No code checkout. All reads via GitHub API.
- name: 🕊️ Survey the zoo
id: analyze
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }}
run: |
set -euo pipefail
# === Count comments from each zoo bot ===
COMMENTS=$(gh api --paginate "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" \
--jq '.[] | {login: .user.login, body: .body}' 2>/dev/null || true)
[ -z "$COMMENTS" ] && { echo "should_comment=false" >> "$GITHUB_OUTPUT"; exit 0; }
JUSTICE=$(echo "$COMMENTS" | jq -s '[.[] | select(.login == "nullvariant-justice[bot]")] | length')
SLOW=$(echo "$COMMENTS" | jq -s '[.[] | select(.login == "nullvariant-slow[bot]")] | length')
MIMI=$(echo "$COMMENTS" | jq -s '[.[] | select(.login == "nullvariant-mimi[bot]")] | length')
LUNA=$(echo "$COMMENTS" | jq -s '[.[] | select(.login == "nullvariant-luna[bot]")] | length')
BLAZE=$(echo "$COMMENTS" | jq -s '[.[] | select(.login == "nullvariant-blaze[bot]")] | length')
TOTAL=$((JUSTICE + SLOW + MIMI + LUNA + BLAZE))
if [ "$TOTAL" -eq 0 ]; then
echo "No zoo bots commented. Nothing to mediate."
echo "should_comment=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# === Check for conflicts (BLOCK vs APPROVE) ===
HAS_BLOCK=$(echo "$COMMENTS" | jq -s '[.[] | select(.body | test("BLOCK|FAILED"; "i"))] | length')
HAS_APPROVE=$(echo "$COMMENTS" | jq -s '[.[] | select(.body | test("APPROVED|looking good"; "i"))] | length')
: > /tmp/ciel-findings.md
# Build zoo status table
{
printf '| Zoo Member | Status |\n'
printf '| --- | --- |\n'
[ "$JUSTICE" -gt 0 ] && printf '| 👮 Justice | Commented |\n'
[ "$SLOW" -gt 0 ] && printf '| 🦥 Slow | Commented |\n'
[ "$MIMI" -gt 0 ] && printf '| 🐰 Mimi | Commented |\n'
[ "$LUNA" -gt 0 ] && printf '| 👧 Luna | Commented |\n'
[ "$BLAZE" -gt 0 ] && printf '| 🐗 Blaze | Commented |\n'
printf '\n'
} >> /tmp/ciel-findings.md
if [ "$TOTAL" -eq 1 ]; then
printf '😴 A quiet day at the zoo. Only one member peeked at this PR.\n\n' >> /tmp/ciel-findings.md
echo "mood=quiet" >> "$GITHUB_OUTPUT"
elif [ "$HAS_BLOCK" -gt 0 ] && [ "$HAS_APPROVE" -gt 0 ]; then
printf '⚖️ The zoo has **mixed opinions**. Some are concerned, some are fine with it. Please review each comment carefully and make the final call.\n\n' >> /tmp/ciel-findings.md
echo "mood=conflict" >> "$GITHUB_OUTPUT"
elif [ "$HAS_BLOCK" -gt 0 ]; then
printf '⛔ The zoo has **concerns**. Please address them before merging.\n\n' >> /tmp/ciel-findings.md
echo "mood=concerned" >> "$GITHUB_OUTPUT"
else
printf '☀️ The zoo is in **harmony**. Everything looks peaceful from up here.\n\n' >> /tmp/ciel-findings.md
echo "mood=peaceful" >> "$GITHUB_OUTPUT"
fi
echo "should_comment=true" >> "$GITHUB_OUTPUT"
echo "total=${TOTAL}" >> "$GITHUB_OUTPUT"
- name: 📬 Post mediation comment
if: steps.analyze.outputs.should_comment == 'true'
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }}
MOOD: ${{ steps.analyze.outputs.mood }}
TOTAL: ${{ steps.analyze.outputs.total }}
run: |
set -euo pipefail
{
case "$MOOD" in
quiet)
printf '## 🕊️ Ciel'"'"'s Mediation 💤\n\n'
printf '*~~ drifting lazily through still air ~~ The zoo is napping today...*\n\n'
;;
conflict)
printf '## 🕊️ Ciel'"'"'s Mediation 🌤️\n\n'
printf '*~~ floating down from the clouds ~~ The zoo seems a bit noisy today...*\n\n'
;;
concerned)
printf '## 🕊️ Ciel'"'"'s Mediation 🌧️\n\n'
printf '*~~ descending through grey clouds ~~ I sense some tension...*\n\n'
;;
peaceful)
printf '## 🕊️ Ciel'"'"'s Mediation ☀️\n\n'
printf '*~~ gliding on a gentle breeze ~~ How serene!*\n\n'
;;
esac
if [ "$TOTAL" -eq 1 ]; then
printf '1 zoo member has reviewed this PR.\n\n'
else
printf '%s zoo members have reviewed this PR.\n\n' "$TOTAL"
fi
cat /tmp/ciel-findings.md
printf '\n---\n\n'
printf '> まあまあ、ほどほどに。\n\n'
printf '*This mediation was peacefully delivered by nullvariant-ciel[bot]*\n'
} > /tmp/ciel-comment.md
EXISTING_ID=$(gh api --paginate "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" \
--jq '.[] | select(.user.login == "nullvariant-ciel[bot]") | select(.body | contains("Ciel\u0027s Mediation")) | .id' 2>/dev/null | head -1 || true)
if [ -n "$EXISTING_ID" ]; then
gh api "repos/${GITHUB_REPOSITORY}/issues/comments/${EXISTING_ID}" \
-X PATCH -F body=@/tmp/ciel-comment.md
else
gh pr comment "$PR_NUMBER" --body-file /tmp/ciel-comment.md
fi
- name: ☁️ Return to the sky
run: echo "Balance has been restored. ~~ ascending ~~ ☁️"
ciel-commit:
name: 🕊️ Descend from the sky
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
permissions:
contents: read
steps:
- name: Harden Runner
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: audit
- name: 🕊️ Arrive gracefully
run: |
echo "~~ floating down from the clouds ~~"
echo "Everything in moderation..."
- name: 🔑 Get App Token
id: app-token
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2
with:
app_id: ${{ secrets.CIEL_BOT_APP_ID }}
private_key: ${{ secrets.CIEL_BOT_PRIVATE_KEY }}
- name: 📥 Checkout (gently)
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ steps.app-token.outputs.token }}
# SECURITY: Use environment variable to prevent script injection
- name: 📝 Leave a peaceful message
env:
USER_MESSAGE: ${{ github.event.inputs.message }}
run: |
mkdir -p docs
cat > docs/CIEL.md << 'EOF'
# 🕊️ Ciel's Sky Notes
> "The sky sees all, judges none."
## Today's Whisper
EOF
printf '%s\n' "${USER_MESSAGE}" >> docs/CIEL.md
cat >> docs/CIEL.md << 'EOF'
---
EOF
echo "*Last descended: $(date -u +"%Y-%m-%d %H:%M:%S UTC")*" >> docs/CIEL.md
cat >> docs/CIEL.md << 'EOF'
> まあまあ、ほどほどに。
EOF
- name: 📬 Create PR with verified commit
env:
USER_MESSAGE: ${{ github.event.inputs.message }}
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ steps.app-token.outputs.token }}
sign-commits: true
author: nullvariant-ciel[bot] <2610776+nullvariant-ciel[bot]@users.noreply.github.com>
committer: nullvariant-ciel[bot] <2610776+nullvariant-ciel[bot]@users.noreply.github.com>
commit-message: |
🕊️ A message from above
${{ env.USER_MESSAGE }}
~~ drifting back to the clouds ~~
branch: ciel/whisper-${{ github.run_number }}
delete-branch: true
title: "🕊️ Ciel's sky notes update"
body: |
## 🕊️ *A gentle breeze*
${{ env.USER_MESSAGE }}
---
> まあまあ、ほどほどに。
*This PR was peacefully delivered by nullvariant-ciel[bot]*
- name: ☁️ Return to the sky
run: |
echo "Balance has been restored."
echo "~~ ascending back to the clouds ~~"