|
| 1 | +name:AI Documentation Updates Automation |
| 2 | + |
| 3 | +on: |
| 4 | +pull_request: |
| 5 | +types: |
| 6 | + -opened |
| 7 | + -synchronize |
| 8 | + -reopened |
| 9 | +workflow_dispatch: |
| 10 | +inputs: |
| 11 | +pr_number: |
| 12 | +description:"Pull Request number to process" |
| 13 | +required:true |
| 14 | +type:number |
| 15 | + |
| 16 | +jobs: |
| 17 | +documentation-check: |
| 18 | +name:Check Documentation Updates with Claude Code |
| 19 | +runs-on:ubuntu-latest |
| 20 | +timeout-minutes:30 |
| 21 | +env: |
| 22 | +CODER_URL:${{ secrets.TRAIAGE_CODER_URL }} |
| 23 | +CODER_SESSION_TOKEN:${{ secrets.TRAIAGE_CODER_SESSION_TOKEN }} |
| 24 | +permissions: |
| 25 | +contents:read |
| 26 | +pull-requests:write |
| 27 | +actions:write |
| 28 | + |
| 29 | +steps: |
| 30 | + -name:Determine PR Number |
| 31 | +id:determine-pr |
| 32 | +env: |
| 33 | +GITHUB_EVENT_NAME:${{ github.event_name }} |
| 34 | +GITHUB_EVENT_PR_NUMBER:${{ github.event.pull_request.number }} |
| 35 | +INPUTS_PR_NUMBER:${{ inputs.pr_number }} |
| 36 | +run:| |
| 37 | + if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then |
| 38 | + echo "pr_number=${INPUTS_PR_NUMBER}" >> "${GITHUB_OUTPUT}" |
| 39 | + elif [[ "${GITHUB_EVENT_NAME}" == "pull_request" ]]; then |
| 40 | + echo "pr_number=${GITHUB_EVENT_PR_NUMBER}" >> "${GITHUB_OUTPUT}" |
| 41 | + else |
| 42 | + echo "::error::Unsupported event type: ${GITHUB_EVENT_NAME}" |
| 43 | + exit 1 |
| 44 | + fi |
| 45 | +
|
| 46 | + -name:Verify push access |
| 47 | +env: |
| 48 | +GITHUB_REPOSITORY:${{ github.repository }} |
| 49 | +GH_TOKEN:${{ github.token }} |
| 50 | +GITHUB_ACTOR:${{ github.actor }} |
| 51 | +run:| |
| 52 | + can_push="$(gh api "/repos/${GITHUB_REPOSITORY}/collaborators/${GITHUB_ACTOR}/permission" --jq '.user.permissions.push')" |
| 53 | + if [[ "${can_push}" != "true" ]]; then |
| 54 | + echo "::error title=Access Denied::${GITHUB_ACTOR} does not have push access to ${GITHUB_REPOSITORY}" |
| 55 | + exit 1 |
| 56 | + fi |
| 57 | +
|
| 58 | + -name:Post initial comment |
| 59 | +id:post-comment |
| 60 | +env: |
| 61 | +GH_TOKEN:${{ github.token }} |
| 62 | +PR_NUMBER:${{ steps.determine-pr.outputs.pr_number }} |
| 63 | +GITHUB_REPOSITORY:${{ github.repository }} |
| 64 | +RUN_ID:${{ github.run_id }} |
| 65 | +run:| |
| 66 | + COMMENT_BODY="🤖 **Documentation Check Started** |
| 67 | +
|
| 68 | +Analyzing PR changes to determine if documentation updates are needed... |
| 69 | + |
| 70 | +[View workflow run](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${RUN_ID}) |
| 71 | +" |
| 72 | + COMMENT_ID=$(gh pr comment"${PR_NUMBER}" --body "${COMMENT_BODY}" --repo "${GITHUB_REPOSITORY}" | grep -oP 'https://github.com/.*/pull/.*#issuecomment-\K\d+') |
| 73 | +echo "comment_id=${COMMENT_ID}" >> "${GITHUB_OUTPUT}" |
| 74 | + |
| 75 | + -name:Download and install Coder binary |
| 76 | +shell:bash |
| 77 | +env: |
| 78 | +CODER_URL:${{ secrets.TRAIAGE_CODER_URL }} |
| 79 | +run:| |
| 80 | + if [ "${{ runner.arch }}" == "ARM64" ]; then |
| 81 | + ARCH="arm64" |
| 82 | + else |
| 83 | + ARCH="amd64" |
| 84 | + fi |
| 85 | + mkdir -p "${HOME}/.local/bin" |
| 86 | + curl -fsSL --compressed "$CODER_URL/bin/coder-linux-${ARCH}" -o "${HOME}/.local/bin/coder" |
| 87 | + chmod +x "${HOME}/.local/bin/coder" |
| 88 | + export PATH="$HOME/.local/bin:$PATH" |
| 89 | + coder version |
| 90 | + coder whoami |
| 91 | + echo "$HOME/.local/bin" >> "${GITHUB_PATH}" |
| 92 | +
|
| 93 | + -name:Get Coder username from GitHub actor |
| 94 | +id:get-coder-username |
| 95 | +env: |
| 96 | +CODER_SESSION_TOKEN:${{ secrets.TRAIAGE_CODER_SESSION_TOKEN }} |
| 97 | +GH_TOKEN:${{ github.token }} |
| 98 | +GITHUB_ACTOR:${{ github.actor }} |
| 99 | +run:| |
| 100 | + GITHUB_USER_ID=$(gh api "users/${GITHUB_ACTOR}" --jq '.id') |
| 101 | + user_json=$(coder users list --github-user-id="${GITHUB_USER_ID}" --output=json) |
| 102 | + coder_username=$(jq -r 'first | .username' <<< "$user_json") |
| 103 | + [[ -z "${coder_username}" || "${coder_username}" == "null" ]] && echo "No Coder user with GitHub user ID ${GITHUB_USER_ID} found" && exit 1 |
| 104 | + echo "coder_username=${coder_username}" >> "${GITHUB_OUTPUT}" |
| 105 | +
|
| 106 | + -name:Checkout repository |
| 107 | +uses:actions/checkout@v4 |
| 108 | +with: |
| 109 | +persist-credentials:false |
| 110 | +fetch-depth:0 |
| 111 | + |
| 112 | + -name:Create Coder task for documentation analysis |
| 113 | +id:create-task |
| 114 | +env: |
| 115 | +CODER_USERNAME:${{ steps.get-coder-username.outputs.coder_username }} |
| 116 | +GH_TOKEN:${{ github.token }} |
| 117 | +GITHUB_REPOSITORY:${{ github.repository }} |
| 118 | +PR_NUMBER:${{ steps.determine-pr.outputs.pr_number }} |
| 119 | +RUN_ID:${{ github.run_id }} |
| 120 | +TEMPLATE_NAME:"traiage" |
| 121 | +TEMPLATE_PRESET:"Default" |
| 122 | +run:| |
| 123 | + # Fetch PR details using `gh` CLI |
| 124 | + pr_json=$(gh pr view "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json 'title,body,url,files') |
| 125 | + pr_title=$(echo "${pr_json}" | jq -r '.title') |
| 126 | + pr_body=$(echo "${pr_json}" | jq -r '.body') |
| 127 | + pr_url=$(echo "${pr_json}" | jq -r '.url') |
| 128 | +
|
| 129 | + # Get list of changed files |
| 130 | + files_changed=$(echo "${pr_json}" | jq -r '.files[] | " - \(.path) (\(.additions) additions, \(.deletions) deletions)"') |
| 131 | +
|
| 132 | + # Get the actual diff for code changes |
| 133 | + pr_diff=$(gh pr diff "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}") |
| 134 | +
|
| 135 | + # Build comprehensive prompt |
| 136 | + PROMPT=$(cat <<EOF |
| 137 | +Analyze PR ${pr_url} for documentation updates. |
| 138 | + |
| 139 | +## Task Description |
| 140 | +You are tasked with analyzing code changes in a pull request and determining what documentation updates are needed. Please: |
| 141 | + |
| 142 | +1. Review the PR description and code changes to understand what was changed |
| 143 | +2. Examine the existing documentation in the docs/ directory |
| 144 | +3. Identify any of the following needs: |
| 145 | + -Updates required to existing documentation |
| 146 | + -Documentation that needs to be deprecated |
| 147 | + -New documentation that should be added |
| 148 | +4. Provide a clear, actionable list of documentation changes needed |
| 149 | + |
| 150 | +## PR Details |
| 151 | +**Title**: ${pr_title} |
| 152 | + |
| 153 | +**Description**: |
| 154 | +${pr_body} |
| 155 | + |
| 156 | +**Files Changed**: |
| 157 | +${files_changed} |
| 158 | + |
| 159 | +**Code Diff**: |
| 160 | +\`\`\`diff |
| 161 | +${pr_diff} |
| 162 | +\`\`\` |
| 163 | + |
| 164 | +## Output Format |
| 165 | +Please provide your analysis in the following format: |
| 166 | + |
| 167 | +### Documentation Updates Required |
| 168 | + |
| 169 | +#### Updates to Existing Documentation |
| 170 | +-[List any existing docs that need updates with specific changes needed] |
| 171 | + |
| 172 | +#### Documentation to Deprecate |
| 173 | +-[List any docs that should be marked as deprecated or removed] |
| 174 | + |
| 175 | +#### New Documentation Needed |
| 176 | +-[List any new documentation that should be created] |
| 177 | + |
| 178 | +#### No Changes Needed |
| 179 | +-[If no documentation changes are required, explain why] |
| 180 | + |
| 181 | +Be specific and provide file paths and section references where applicable. |
| 182 | +EOF |
| 183 | +) |
| 184 | +export PROMPT |
| 185 | + |
| 186 | +export TASK_NAME="doccheck-pr-${PR_NUMBER}-${RUN_ID}" |
| 187 | +export CONTEXT_KEY="gh-pr-${PR_NUMBER}" |
| 188 | +echo "Creating task:${CODER_USERNAME}/${TASK_NAME}" |
| 189 | + |
| 190 | +./scripts/documentation-check.sh create |
| 191 | + |
| 192 | +echo "TASK_NAME=${CODER_USERNAME}/${TASK_NAME}" >> "${GITHUB_OUTPUT}" |
| 193 | +echo "TASK_NAME=${CODER_USERNAME}/${TASK_NAME}" >> "${GITHUB_ENV}" |
| 194 | + |
| 195 | + -name:Wait for task completion and get results |
| 196 | +id:get-results |
| 197 | +env: |
| 198 | +TASK_NAME:${{ steps.create-task.outputs.TASK_NAME }} |
| 199 | +run:| |
| 200 | + echo "Waiting for task to complete..." |
| 201 | + ./scripts/documentation-check.sh wait |
| 202 | +
|
| 203 | + echo "Getting task results..." |
| 204 | + TASK_OUTPUT=$(./scripts/documentation-check.sh summary) |
| 205 | +
|
| 206 | + # Save output to file for next step |
| 207 | + echo "${TASK_OUTPUT}" > /tmp/task_output.txt |
| 208 | +
|
| 209 | + echo "Task completed successfully" |
| 210 | +
|
| 211 | + -name:Update PR comment with results |
| 212 | +env: |
| 213 | +GH_TOKEN:${{ github.token }} |
| 214 | +PR_NUMBER:${{ steps.determine-pr.outputs.pr_number }} |
| 215 | +GITHUB_REPOSITORY:${{ github.repository }} |
| 216 | +COMMENT_ID:${{ steps.post-comment.outputs.comment_id }} |
| 217 | +TASK_NAME:${{ steps.create-task.outputs.TASK_NAME }} |
| 218 | +RUN_ID:${{ github.run_id }} |
| 219 | +run:| |
| 220 | + TASK_OUTPUT=$(cat /tmp/task_output.txt) |
| 221 | +
|
| 222 | + COMMENT_BODY="🤖 **Documentation Check Complete** |
| 223 | +
|
| 224 | +${TASK_OUTPUT} |
| 225 | + |
| 226 | +--- |
| 227 | +Task:https://dev.coder.com/tasks/${TASK_NAME} |
| 228 | +[View workflow run](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${RUN_ID}) |
| 229 | +" |
| 230 | +
|
| 231 | + # Update the existing comment |
| 232 | + gh api \ |
| 233 | + --method PATCH \ |
| 234 | +"/repos/${GITHUB_REPOSITORY}/issues/comments/${COMMENT_ID}" \ |
| 235 | +-f body="${COMMENT_BODY}" |
| 236 | + |
| 237 | + -name:Cleanup task |
| 238 | +if:always() |
| 239 | +env: |
| 240 | +TASK_NAME:${{ steps.create-task.outputs.TASK_NAME }} |
| 241 | +run:| |
| 242 | + if [[ -n "${TASK_NAME}" ]]; then |
| 243 | + echo "Cleaning up task: ${TASK_NAME}" |
| 244 | + ./scripts/documentation-check.sh delete ||true |
| 245 | + fi |