🕊️ Ciel Bot #462
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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 ~~" |