mirror of
https://github.com/mattermost/mattermost.git
synced 2026-08-27 05:37:15 -05:00
fix(pr-analysis): on large diff and reduce gh pr calls (#35734)
* fix(pr-analysis): on large diff and reduce gh pr calls * address comments
This commit is contained in:
@@ -50,25 +50,40 @@ jobs:
|
||||
id: pr-info
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
# Pass event data via env vars to avoid script injection from PR body
|
||||
EVENT_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
EVENT_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
EVENT_REPO_OWNER: ${{ github.repository_owner }}
|
||||
EVENT_REPO_NAME: ${{ github.event.repository.name }}
|
||||
EVENT_PR_BODY: ${{ github.event.pull_request.body }}
|
||||
EVENT_BASE_REF: ${{ github.event.pull_request.base.ref }}
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
PR_NUMBER="${{ inputs.pr_number }}"
|
||||
PR_JSON=$(gh pr view "$PR_NUMBER" --repo "${{ env.REPO }}" --json headRefOid,headRepository,headRepositoryOwner --jq '{sha: .headRefOid, repo: .headRepository.name, owner: .headRepositoryOwner.login}')
|
||||
HEAD_SHA=$(echo "$PR_JSON" | jq -r '.sha')
|
||||
HEAD_REPO_OWNER=$(echo "$PR_JSON" | jq -r '.owner')
|
||||
HEAD_REPO_NAME=$(echo "$PR_JSON" | jq -r '.repo')
|
||||
PR_JSON=$(gh pr view "$PR_NUMBER" --repo "${{ env.REPO }}" --json headRefOid,headRepository,headRepositoryOwner,body,baseRefName)
|
||||
HEAD_SHA=$(echo "$PR_JSON" | jq -r '.headRefOid')
|
||||
HEAD_REPO_OWNER=$(echo "$PR_JSON" | jq -r '.headRepositoryOwner.login')
|
||||
HEAD_REPO_NAME=$(echo "$PR_JSON" | jq -r '.headRepository.name')
|
||||
PR_BODY=$(echo "$PR_JSON" | jq -r '.body // ""')
|
||||
BASE_BRANCH=$(echo "$PR_JSON" | jq -r '.baseRefName')
|
||||
else
|
||||
PR_NUMBER="${{ github.event.pull_request.number }}"
|
||||
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
|
||||
HEAD_REPO_OWNER="${{ github.repository_owner }}"
|
||||
HEAD_REPO_NAME="${{ github.event.repository.name }}"
|
||||
PR_NUMBER="$EVENT_PR_NUMBER"
|
||||
HEAD_SHA="$EVENT_HEAD_SHA"
|
||||
HEAD_REPO_OWNER="$EVENT_REPO_OWNER"
|
||||
HEAD_REPO_NAME="$EVENT_REPO_NAME"
|
||||
PR_BODY="$EVENT_PR_BODY"
|
||||
BASE_BRANCH="$EVENT_BASE_REF"
|
||||
fi
|
||||
{
|
||||
echo "pr_number=${PR_NUMBER}"
|
||||
echo "head_sha=${HEAD_SHA}"
|
||||
echo "head_repo=${HEAD_REPO_OWNER}/${HEAD_REPO_NAME}"
|
||||
echo "base_branch=${BASE_BRANCH}"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Write PR body to a temp path that survives checkout
|
||||
printf '%s\n' "$PR_BODY" > "$RUNNER_TEMP/pr_body.txt"
|
||||
|
||||
# Required: claude-code-action needs a git directory to initialize.
|
||||
- name: ci/checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
@@ -77,15 +92,24 @@ jobs:
|
||||
|
||||
- name: ci/prep-analysis-data
|
||||
id: prep
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
PR_NUM=${{ steps.pr-info.outputs.pr_number }}
|
||||
# Fetch core data
|
||||
gh pr view "$PR_NUM" --repo "$REPO" --json body --jq '.body' > pr_body.txt
|
||||
BASE_BRANCH=${{ steps.pr-info.outputs.base_branch }}
|
||||
|
||||
# Get all changed files
|
||||
gh pr diff "$PR_NUM" --repo "$REPO" --name-only > all_files.txt
|
||||
# Copy PR body from temp path (written before checkout)
|
||||
cp "$RUNNER_TEMP/pr_body.txt" pr_body.txt
|
||||
|
||||
# Fetch the PR head and base branch, then diff locally (no API size limits)
|
||||
git fetch origin "$BASE_BRANCH" "pull/$PR_NUM/head:pr-$PR_NUM" --depth=50
|
||||
if ! MERGE_BASE=$(git merge-base "origin/$BASE_BRANCH" "pr-$PR_NUM" 2>/dev/null); then
|
||||
echo "Merge base not found in shallow history — fetching full history"
|
||||
git fetch --unshallow origin "$BASE_BRANCH" "pull/$PR_NUM/head:pr-$PR_NUM"
|
||||
MERGE_BASE=$(git merge-base "origin/$BASE_BRANCH" "pr-$PR_NUM")
|
||||
fi
|
||||
git diff "$MERGE_BASE" "pr-$PR_NUM" > full_diff.diff
|
||||
|
||||
# Derive file list from the diff (avoids a second API call)
|
||||
grep '^diff --git' full_diff.diff | sed 's|.*b/||' > all_files.txt
|
||||
|
||||
# Extract Test Files (based on your conventions)
|
||||
grep -E "_test\.go|\.test\.(ts|tsx|js)|e2e-tests/|detox/|e2e/" all_files.txt > test_files.txt || true
|
||||
@@ -97,10 +121,7 @@ jobs:
|
||||
cat prod_files.txt test_files.txt | sort | uniq > relevant_files.txt
|
||||
|
||||
if [ -s relevant_files.txt ]; then
|
||||
# Fetch the full diff, then filter to keep only hunks for relevant files
|
||||
gh pr diff "$PR_NUM" --repo "$REPO" > full_diff.diff
|
||||
|
||||
# Use awk to extract only diff sections whose header matches a relevant file
|
||||
# Filter the already-fetched diff to keep only hunks for relevant files
|
||||
awk '
|
||||
BEGIN { while ((getline line < "relevant_files.txt") > 0) files[line]=1 }
|
||||
/^diff --git/ {
|
||||
@@ -109,12 +130,12 @@ jobs:
|
||||
}
|
||||
printing { print }
|
||||
' full_diff.diff > filtered_diff.diff
|
||||
|
||||
rm -f full_diff.diff
|
||||
else
|
||||
touch filtered_diff.diff
|
||||
fi
|
||||
|
||||
rm -f full_diff.diff
|
||||
|
||||
- name: ci/analyze-tests
|
||||
id: ai-analysis
|
||||
continue-on-error: true
|
||||
|
||||
Reference in New Issue
Block a user