|
name: PI PR Agent |
|
|
|
on: |
|
pull_request_review_comment: |
|
types: [created] |
|
issue_comment: |
|
types: [created] |
|
|
|
concurrency: |
|
group: pi-pr-${{ github.event.pull_request.number || github.event.issue.number }} |
|
cancel-in-progress: true |
|
|
|
permissions: |
|
actions: read |
|
issues: write |
|
contents: write |
|
pull-requests: write |
|
|
|
jobs: |
|
agent: |
|
runs-on: ubuntu-latest |
|
if: | |
|
contains(github.server_url, 'github.com') |
|
&& github.event.comment.user.type != 'Bot' |
|
&& !contains(github.event.comment.body, '<!-- PI-BOT-COMMENT -->') |
|
&& ( |
|
(github.event_name == 'pull_request_review_comment' && github.event.pull_request != null) |
|
|| (github.event_name == 'issue_comment' && github.event.issue.pull_request != null) |
|
) |
|
|
|
steps: |
|
- name: Check for @pi trigger |
|
id: check-trigger |
|
env: |
|
COMMENT_BODY: ${{ github.event.comment.body }} |
|
run: | |
|
# Check if comment contains @pi with word boundaries (case-sensitive) |
|
# Word boundary: start of string, whitespace, or punctuation before @pi |
|
# and whitespace, punctuation, or end of string after @pi |
|
if echo "$COMMENT_BODY" | grep -qP '(?<=^|[[:space:]])@pi(?=[[:space:]]|$|[[:punct:]])'; then |
|
echo "triggered=true" >> $GITHUB_OUTPUT |
|
else |
|
echo "triggered=false" >> $GITHUB_OUTPUT |
|
echo "Comment does not contain @pi trigger, skipping." |
|
exit 0 |
|
fi |
|
|
|
- name: Validate configuration |
|
if: steps.check-trigger.outputs.triggered == 'true' |
|
id: validate-config |
|
env: |
|
PI_SETTINGS: ${{ vars.PI_SETTINGS }} |
|
PI_AUTH_JSON: ${{ secrets.PI_AUTH_JSON }} |
|
run: | |
|
MISSING="" |
|
[ -z "$PI_SETTINGS" ] && MISSING="$MISSING PI_SETTINGS" |
|
[ -z "$PI_AUTH_JSON" ] && MISSING="$MISSING PI_AUTH_JSON" |
|
|
|
if [ -n "$MISSING" ]; then |
|
echo "Required PI configuration not set:$MISSING" |
|
echo "config_valid=false" >> $GITHUB_OUTPUT |
|
else |
|
echo "config_valid=true" >> $GITHUB_OUTPUT |
|
fi |
|
|
|
- name: Add eyes reaction |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' |
|
env: |
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
COMMENT_ID: ${{ github.event.comment.id }} |
|
GITHUB_REPO: ${{ github.repository }} |
|
EVENT_NAME: ${{ github.event_name }} |
|
run: | |
|
if [[ "$EVENT_NAME" == "pull_request_review_comment" ]]; then |
|
ENDPOINT="pulls/comments" |
|
else |
|
ENDPOINT="issues/comments" |
|
fi |
|
gh api "repos/$GITHUB_REPO/$ENDPOINT/$COMMENT_ID/reactions" \ |
|
-X POST \ |
|
-f content="eyes" || echo "Failed to add eyes reaction" >&2 |
|
|
|
- name: Normalize PR data |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' |
|
id: pr-data |
|
env: |
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} |
|
PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} |
|
PR_TITLE: ${{ github.event.pull_request.title }} |
|
PR_STATE: ${{ github.event.pull_request.state }} |
|
PR_MERGED: ${{ github.event.pull_request.merged }} |
|
PR_BODY: ${{ github.event.pull_request.body }} |
|
COMMENT_PATH: ${{ github.event.comment.path }} |
|
COMMENT_LINE: ${{ github.event.comment.line }} |
|
COMMENT_DIFF_HUNK: ${{ github.event.comment.diff_hunk }} |
|
EVENT_NAME: ${{ github.event_name }} |
|
REPO: ${{ github.repository }} |
|
run: | |
|
if [[ "$EVENT_NAME" == "pull_request_review_comment" ]]; then |
|
# Direct access for review comments |
|
echo "number=$PR_NUMBER" >> $GITHUB_OUTPUT |
|
echo "head_ref=$PR_HEAD_REF" >> $GITHUB_OUTPUT |
|
echo "title=$PR_TITLE" >> $GITHUB_OUTPUT |
|
echo "state=$PR_STATE" >> $GITHUB_OUTPUT |
|
echo "merged=$PR_MERGED" >> $GITHUB_OUTPUT |
|
# Use jq for proper JSON escaping of PR body - use heredoc syntax for multi-line |
|
echo "body<<PRBODYEOF" >> $GITHUB_OUTPUT |
|
echo "$PR_BODY" | jq -Rs '.' >> $GITHUB_OUTPUT |
|
echo "PRBODYEOF" >> $GITHUB_OUTPUT |
|
# Build context JSON using jq for proper escaping |
|
CONTEXT_JSON=$(jq -n \ |
|
--arg path "$COMMENT_PATH" \ |
|
--argjson line "${COMMENT_LINE:-null}" \ |
|
--arg diff_hunk "$COMMENT_DIFF_HUNK" \ |
|
'{path: $path, line: $line, diff_hunk: $diff_hunk}') |
|
# Use heredoc syntax for multi-line context |
|
echo "comment_context<<CTXT" >> $GITHUB_OUTPUT |
|
echo "$CONTEXT_JSON" >> $GITHUB_OUTPUT |
|
echo "CTXT" >> $GITHUB_OUTPUT |
|
else |
|
# API fetch for issue comments on PRs |
|
PR_DATA=$(gh api "repos/$REPO/pulls/$PR_NUMBER") |
|
echo "number=$PR_NUMBER" >> $GITHUB_OUTPUT |
|
echo "head_ref=$(echo "$PR_DATA" | jq -r '.head.ref')" >> $GITHUB_OUTPUT |
|
echo "title=$(echo "$PR_DATA" | jq -r '.title')" >> $GITHUB_OUTPUT |
|
echo "state=$(echo "$PR_DATA" | jq -r '.state')" >> $GITHUB_OUTPUT |
|
echo "merged=$(echo "$PR_DATA" | jq -r '.merged')" >> $GITHUB_OUTPUT |
|
# Use jq for proper JSON escaping of PR body - use heredoc syntax for multi-line |
|
PR_BODY_FETCHED=$(echo "$PR_DATA" | jq -r '.body') |
|
echo "body<<PRBODYEOF" >> $GITHUB_OUTPUT |
|
echo "$PR_BODY_FETCHED" | jq -Rs '.' >> $GITHUB_OUTPUT |
|
echo "PRBODYEOF" >> $GITHUB_OUTPUT |
|
# No review context for issue_comment events |
|
echo 'comment_context={}' >> $GITHUB_OUTPUT |
|
fi |
|
|
|
- name: Validate PR state |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' |
|
id: validate-state |
|
run: | |
|
if [[ "${{ steps.pr-data.outputs.state }}" == "closed" ]] || [[ "${{ steps.pr-data.outputs.merged }}" == "true" ]]; then |
|
echo "valid=false" >> $GITHUB_OUTPUT |
|
echo "PR is closed or merged, skipping." |
|
exit 0 |
|
else |
|
echo "valid=true" >> $GITHUB_OUTPUT |
|
fi |
|
|
|
- name: Setup Node.js |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' |
|
uses: actions/setup-node@v6 |
|
with: |
|
node-version: '20.19.0' |
|
|
|
- name: Install PI agent |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' |
|
run: npm install -g @mariozechner/pi-coding-agent |
|
|
|
- name: Install OpenSpec CLI |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' |
|
run: npm install -g @fission-ai/openspec@latest |
|
|
|
- name: Configure PI agent |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' |
|
env: |
|
PI_SETTINGS: ${{ vars.PI_SETTINGS }} |
|
PI_AUTH_JSON: ${{ secrets.PI_AUTH_JSON }} |
|
run: | |
|
mkdir -p ~/.pi/agent |
|
mkdir -p ~/.pi/sessions |
|
|
|
echo "$PI_AUTH_JSON" > ~/.pi/agent/auth.json |
|
echo "$PI_SETTINGS" > ~/.pi/agent/settings.json |
|
|
|
chmod 600 ~/.pi/agent/auth.json |
|
|
|
- name: Find last PI-BOT-COMMENT in PR |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' |
|
id: find-comment |
|
env: |
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
PR_NUMBER: ${{ steps.pr-data.outputs.number }} |
|
GITHUB_REPO: ${{ github.repository }} |
|
run: | |
|
# Fetch all issue comments on the PR and find the last one with PI-BOT-COMMENT marker |
|
COMMENTS=$(gh api "repos/$GITHUB_REPO/issues/$PR_NUMBER/comments" --paginate -q '.[] | select(.body | contains("<!-- PI-BOT-COMMENT -->")) | {id: .id, body: .body, created_at: .created_at}' | jq -s 'sort_by(.created_at) | last') |
|
|
|
if [ -n "$COMMENTS" ] && [ "$COMMENTS" != "null" ]; then |
|
echo "found=true" >> $GITHUB_OUTPUT |
|
echo "body<<EOF" >> $GITHUB_OUTPUT |
|
echo "$COMMENTS" | jq -r '.body' >> $GITHUB_OUTPUT |
|
echo "EOF" >> $GITHUB_OUTPUT |
|
else |
|
echo "found=false" >> $GITHUB_OUTPUT |
|
fi |
|
|
|
- name: Extract SESSION marker |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' && steps.find-comment.outputs.found == 'true' |
|
id: extract-session |
|
env: |
|
COMMENT_BODY: ${{ steps.find-comment.outputs.body }} |
|
run: | |
|
# Extract artifact name and run ID from SESSION marker |
|
SESSION_MARKER=$(echo "$COMMENT_BODY" | grep -oP '(?<=<!-- SESSION: ).*?(?= -->)' || true) |
|
|
|
if [ -n "$SESSION_MARKER" ]; then |
|
ARTIFACT_NAME=$(echo "$SESSION_MARKER" | grep -oP '(?<=artifact=)[^,]+' || true) |
|
RUN_ID=$(echo "$SESSION_MARKER" | grep -oP '(?<=run=)[^,]+' || true) |
|
|
|
if [ -n "$ARTIFACT_NAME" ] && [ -n "$RUN_ID" ]; then |
|
echo "has_marker=true" >> $GITHUB_OUTPUT |
|
echo "artifact_name=$ARTIFACT_NAME" >> $GITHUB_OUTPUT |
|
echo "run_id=$RUN_ID" >> $GITHUB_OUTPUT |
|
else |
|
echo "has_marker=false" >> $GITHUB_OUTPUT |
|
fi |
|
else |
|
echo "has_marker=false" >> $GITHUB_OUTPUT |
|
fi |
|
|
|
- name: Download session artifact |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' && steps.extract-session.outputs.has_marker == 'true' |
|
id: download-artifact |
|
uses: actions/download-artifact@v4 |
|
with: |
|
name: ${{ steps.extract-session.outputs.artifact_name }} |
|
path: ~/.pi/sessions |
|
run-id: ${{ steps.extract-session.outputs.run_id }} |
|
github-token: ${{ secrets.GITHUB_TOKEN }} |
|
|
|
- name: Check session existence |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' |
|
id: session-check |
|
env: |
|
PR_NUMBER: ${{ steps.pr-data.outputs.number }} |
|
run: | |
|
SESSION_PATH="$HOME/.pi/sessions/pr-${PR_NUMBER}.jsonl" |
|
if [ -f "$SESSION_PATH" ]; then |
|
echo "exists=true" >> $GITHUB_OUTPUT |
|
else |
|
echo "exists=false" >> $GITHUB_OUTPUT |
|
fi |
|
echo "path=$SESSION_PATH" >> $GITHUB_OUTPUT |
|
|
|
- name: Checkout PR branch |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' |
|
uses: actions/checkout@v6 |
|
with: |
|
ref: ${{ steps.pr-data.outputs.head_ref }} |
|
fetch-depth: 1 |
|
|
|
- name: Build prompt |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' |
|
env: |
|
COMMENT_BODY: ${{ github.event.comment.body }} |
|
COMMENT_CONTEXT: ${{ steps.pr-data.outputs.comment_context }} |
|
run: | |
|
COMMENT_WITHOUT_COMMAND=$(echo "$COMMENT_BODY" | sed -E 's/(^|[[:space:]])@pi([[:space:]]|[[:punct:]]|$)/\1/; s/^[[:space:]]*//') |
|
|
|
# Check if review comment context exists and is non-empty |
|
if [ -n "$COMMENT_CONTEXT" ] && [ "$COMMENT_CONTEXT" != "{}" ]; then |
|
# Build prompt with review context for pull_request_review_comment events |
|
{ |
|
echo "User request: $COMMENT_WITHOUT_COMMAND" |
|
echo "" |
|
echo "Review context (file:line):" |
|
echo '```json' |
|
echo "$COMMENT_CONTEXT" |
|
echo '```' |
|
} > /tmp/prompt.txt |
|
else |
|
# Simple prompt for issue_comment events (backward compatible) |
|
echo "$COMMENT_WITHOUT_COMMAND" > /tmp/prompt.txt |
|
fi |
|
|
|
- name: Run PI agent |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' |
|
id: run-agent |
|
env: |
|
SESSION_PATH: ${{ steps.session-check.outputs.path }} |
|
run: | |
|
RESPONSE=$(cat /tmp/prompt.txt | pi -p --session "$SESSION_PATH" 2>&1) |
|
EXIT_CODE=$? |
|
|
|
if [ $EXIT_CODE -ne 0 ]; then |
|
echo "error=true" >> $GITHUB_OUTPUT |
|
echo "error_message=$RESPONSE" >> $GITHUB_OUTPUT |
|
fi |
|
|
|
echo "response<<EOF" >> $GITHUB_ENV |
|
echo "$RESPONSE" >> $GITHUB_ENV |
|
echo "EOF" >> $GITHUB_ENV |
|
|
|
- name: Configure git user |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' |
|
run: | |
|
git config user.name "PI Agent" |
|
git config user.email "pi-agent@example.com" |
|
|
|
- name: Check for file changes |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' |
|
id: check-changes |
|
run: | |
|
if [[ -n "$(git status --porcelain)" ]]; then |
|
echo "has_changes=true" >> $GITHUB_OUTPUT |
|
else |
|
echo "has_changes=false" >> $GITHUB_OUTPUT |
|
fi |
|
|
|
- name: Add rocket reaction |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' && steps.check-changes.outputs.has_changes == 'true' |
|
env: |
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
COMMENT_ID: ${{ github.event.comment.id }} |
|
GITHUB_REPO: ${{ github.repository }} |
|
EVENT_NAME: ${{ github.event_name }} |
|
run: | |
|
if [[ "$EVENT_NAME" == "pull_request_review_comment" ]]; then |
|
ENDPOINT="pulls/comments" |
|
else |
|
ENDPOINT="issues/comments" |
|
fi |
|
gh api "repos/$GITHUB_REPO/$ENDPOINT/$COMMENT_ID/reactions" \ |
|
-X POST \ |
|
-f content="rocket" || echo "Failed to add rocket reaction" >&2 |
|
|
|
- name: Commit and push changes |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' && steps.check-changes.outputs.has_changes == 'true' |
|
id: commit-push |
|
run: | |
|
git add -A |
|
# Let the PI agent handle the commit |
|
pi -p "$COMMIT_PROMPT" 2>&1 |
|
# Push the commit |
|
git push || exit 1 |
|
env: |
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
COMMIT_PROMPT: | |
|
Review the staged changes and commit them with an appropriate conventional commit message. |
|
|
|
Guidelines: |
|
- Use conventional commit format: feat:, fix:, refactor:, docs:, test:, chore:, etc. |
|
- Write a concise but descriptive message |
|
- Focus on WHAT changed and WHY, not HOW |
|
- Use git commit -m 'message' to commit the changes |
|
|
|
- name: Define metadata prompt |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' && steps.check-changes.outputs.has_changes == 'true' |
|
id: define-metadata-prompt |
|
run: | |
|
cat << 'METADATA_EOF' > /tmp/metadata_prompt.txt |
|
This is a pull request. Compare the current branch with main and generate an updated PR description. |
|
|
|
Output ONLY a JSON object with no other text, no markdown fences, no explanation. |
|
The JSON must have this schema: |
|
{ |
|
"title": "A concise conventional-commit style title for the PR", |
|
"description": "A detailed description of the changes including a '## Changes' section" |
|
} |
|
|
|
Correct output example: |
|
{"title": "feat: update authentication", "description": "## Changes\n\n- Fixed token refresh issue\n- Added auto-logout on expiry\n\nRelated to #42, #43"} |
|
|
|
Incorrect output example (DO NOT DO THIS): |
|
```json |
|
{"title": "feat: update auth", "description": "..."} |
|
``` |
|
|
|
Instructions: |
|
- Compare the current branch against main |
|
- Examine the diff to understand what changed |
|
- Generate a meaningful title that summarizes the actual changes |
|
- Write a description that clearly explains what was done and why |
|
- Include "Related to #N" for each related issue reference in the description |
|
- Output ONLY valid JSON, nothing else |
|
METADATA_EOF |
|
echo "prompt_file=/tmp/metadata_prompt.txt" >> $GITHUB_OUTPUT |
|
|
|
- name: Fetch issue references |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' && steps.check-changes.outputs.has_changes == 'true' |
|
id: fetch-issue-refs |
|
env: |
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
PR_NUMBER: ${{ steps.pr-data.outputs.number }} |
|
GITHUB_REPO: ${{ github.repository }} |
|
run: | |
|
ISSUE_REFS=$(gh pr view $PR_NUMBER --json closedIssueReferences -q '.closedIssueReferences[] | "#\(.number)"' 2>/dev/null | tr '\n' ', ' | sed 's/, $//') |
|
if [ -n "$ISSUE_REFS" ]; then |
|
echo "has_refs=true" >> $GITHUB_OUTPUT |
|
echo "refs=$ISSUE_REFS" >> $GITHUB_OUTPUT |
|
else |
|
echo "has_refs=false" >> $GITHUB_OUTPUT |
|
echo "refs=" >> $GITHUB_OUTPUT |
|
fi |
|
|
|
- name: Generate PR metadata |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' && steps.check-changes.outputs.has_changes == 'true' |
|
id: generate-metadata |
|
run: | |
|
ISSUE_REFS="${{ steps.fetch-issue-refs.outputs.refs }}" |
|
METADATA_PROMPT=$(cat "${{ steps.define-metadata-prompt.outputs.prompt_file }}") |
|
if [ "${{ steps.fetch-issue-refs.outputs.has_refs }}" == "true" ]; then |
|
METADATA_PROMPT_WITH_REFS="$METADATA_PROMPT"$'\n\n'"Related issues: $ISSUE_REFS" |
|
else |
|
METADATA_PROMPT_WITH_REFS="$METADATA_PROMPT" |
|
fi |
|
|
|
METADATA_RESPONSE=$(pi -p "$METADATA_PROMPT_WITH_REFS" 2>&1) |
|
EXIT_CODE=$? |
|
|
|
if [ $EXIT_CODE -ne 0 ]; then |
|
echo "error=true" >> $GITHUB_OUTPUT |
|
echo "error_message=$METADATA_RESPONSE" >> $GITHUB_OUTPUT |
|
echo "Failed to generate PR metadata" >&2 |
|
exit 1 |
|
fi |
|
|
|
DESCRIPTION=$(echo "$METADATA_RESPONSE" | jq -r '.description') |
|
|
|
if [ -z "$DESCRIPTION" ] || [ "$DESCRIPTION" = "null" ]; then |
|
echo "error=true" >> $GITHUB_OUTPUT |
|
echo "error_message=Agent did not return valid JSON with description field" >> $GITHUB_OUTPUT |
|
echo "Failed to parse PR description: agent did not return valid JSON" >&2 |
|
exit 1 |
|
fi |
|
|
|
echo "description<<EOF" >> $GITHUB_OUTPUT |
|
echo "$DESCRIPTION" >> $GITHUB_OUTPUT |
|
echo "EOF" >> $GITHUB_OUTPUT |
|
|
|
- name: Update PR description |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' && steps.check-changes.outputs.has_changes == 'true' && steps.generate-metadata.outputs.error != 'true' |
|
env: |
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
PR_NUMBER: ${{ steps.pr-data.outputs.number }} |
|
GITHUB_REPO: ${{ github.repository }} |
|
DESCRIPTION: ${{ steps.generate-metadata.outputs.description }} |
|
run: | |
|
gh pr edit $PR_NUMBER --body "$DESCRIPTION" |
|
|
|
- name: Post error comment |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' && steps.run-agent.outputs.error == 'true' |
|
env: |
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
PR_NUMBER: ${{ steps.pr-data.outputs.number }} |
|
GITHUB_REPO: ${{ github.repository }} |
|
ERROR_MSG: ${{ steps.run-agent.outputs.error_message }} |
|
ARTIFACT_NAME: pi-session-pr-${{ steps.pr-data.outputs.number }}-${{ github.run_id }} |
|
RUN_ID: ${{ github.run_id }} |
|
run: | |
|
ERROR_BODY="<!-- PI-BOT-COMMENT -->\n<!-- SESSION: artifact=${ARTIFACT_NAME},run=${RUN_ID} -->\n\nβ οΈ **Error**\n\nAn error occurred:\n\`\`\`\n$ERROR_MSG\n\`\`\`" |
|
gh api "repos/$GITHUB_REPO/issues/$PR_NUMBER/comments" -f body="$ERROR_BODY" |
|
|
|
- name: Upload session artifact |
|
if: (steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true') || cancelled() |
|
id: upload-artifact |
|
uses: actions/upload-artifact@v4 |
|
with: |
|
name: pi-session-pr-${{ steps.pr-data.outputs.number }}-${{ github.run_id }} |
|
path: ~/.pi/sessions |
|
retention-days: 7 |
|
if-no-files-found: ignore |
|
|
|
- name: Post response comment |
|
if: steps.check-trigger.outputs.triggered == 'true' && steps.validate-config.outputs.config_valid == 'true' && steps.validate-state.outputs.valid == 'true' && steps.run-agent.outputs.error != 'true' |
|
env: |
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
PR_NUMBER: ${{ steps.pr-data.outputs.number }} |
|
GITHUB_REPO: ${{ github.repository }} |
|
RESPONSE: ${{ env.response }} |
|
ARTIFACT_NAME: pi-session-pr-${{ steps.pr-data.outputs.number }}-${{ github.run_id }} |
|
RUN_ID: ${{ github.run_id }} |
|
run: | |
|
{ |
|
echo "<!-- PI-BOT-COMMENT -->" |
|
echo "<!-- SESSION: artifact=${ARTIFACT_NAME},run=${RUN_ID} -->" |
|
echo "" |
|
printf '%s' "$RESPONSE" |
|
} > /tmp/response_body.txt |
|
|
|
gh api "repos/$GITHUB_REPO/issues/$PR_NUMBER/comments" \ |
|
-f body="$(cat /tmp/response_body.txt)" |