Skip to content

Commit 1792e9c

Browse files
committed
do a clone
1 parent d315e66 commit 1792e9c

File tree

1 file changed

+88
-101
lines changed

1 file changed

+88
-101
lines changed

.github/workflows/upstream-fix-check.yml

Lines changed: 88 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ jobs:
1313
run: |
1414
sudo apt-get update && sudo apt-get install -y jq
1515
16+
- name: Clone Linux Kernel (Bare) # Step 0: Perform a bare clone of the Linux kernel repository
17+
run: |
18+
echo "Cloning Linux kernel repository (bare clone, single branch, no blobs)..."
19+
git clone --bare --filter=blob:none --single-branch https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux.git
20+
echo "Cloning complete."
21+
1622
- name: Get PR commit SHAs via GitHub API # Step 1: Get the list of all commit SHAs in the current Pull Request using GitHub API
1723
id: pr_commits # Assigns an ID to this step to reference its outputs
1824
env:
@@ -44,35 +50,27 @@ jobs:
4450
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4551
LINUX_KERNEL_REPO_OWNER: torvalds
4652
LINUX_KERNEL_REPO_NAME: linux
47-
# Safeguard: Max pages to fetch. Adjust if your referenced commits are extremely old
48-
# and their fixes are deep in history, but be mindful of API rate limits and job duration.
49-
MAX_PAGES_TO_FETCH: 100 # 100 pages * 100 commits/page = 10,000 commits max
5053
run: |
5154
# Use printf -v for robust multi-line string accumulation for the PR comment
5255
PR_COMMENT_BODY_ACCUMULATOR=""
5356
5457
# Get the HEAD commit SHA and its date for the Linux kernel master branch
55-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%sGetting current HEAD of '%s/%s' master branch...\n" \
58+
printf -v PR_COMMENT_BODY_ACCUMULATOR "%sGetting current HEAD of '%s/%s' master branch from local bare clone...\n" \
5659
"$PR_COMMENT_BODY_ACCUMULATOR" "$LINUX_KERNEL_REPO_OWNER" "$LINUX_KERNEL_REPO_NAME"
5760
58-
HEAD_COMMIT_DETAILS_JSON=$(curl -sS -H "Accept: application/vnd.github.v3+json" \
59-
-H "Authorization: token $GITHUB_TOKEN" \
60-
"https://api.github.com/repos/${LINUX_KERNEL_REPO_OWNER}/${LINUX_KERNEL_REPO_NAME}/commits/master")
61+
HEAD_COMMIT_SHA=$(git -C linux.git rev-parse master)
62+
# Get committer date in ISO 8601 format for `git log --until`
63+
HEAD_COMMIT_DATE=$(git -C linux.git show -s --format=%cI master)
6164
62-
ERROR_MESSAGE=$(echo "$HEAD_COMMIT_DETAILS_JSON" | jq -r 'if type == "object" and .message then .message else null end')
63-
if [ "$ERROR_MESSAGE" != "null" ] && [ -n "$ERROR_MESSAGE" ]; then
64-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s ERROR: Could not retrieve HEAD commit for Linux kernel master: %s\n" \
65-
"$PR_COMMENT_BODY_ACCUMULATOR" "$ERROR_MESSAGE"
66-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s API Response snippet: %s\n" \
67-
"$PR_COMMENT_BODY_ACCUMULATOR" "$(echo "$HEAD_COMMIT_DETAILS_JSON" | head -n 5)"
65+
if [ -z "$HEAD_COMMIT_SHA" ] || [ -z "$HEAD_COMMIT_DATE" ]; then
66+
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s ERROR: Could not retrieve HEAD commit or date for Linux kernel master from local clone.\n" \
67+
"$PR_COMMENT_BODY_ACCUMULATOR"
6868
echo "PR_COMMENT_BODY<<EOF" >> "$GITHUB_OUTPUT"
6969
echo "$PR_COMMENT_BODY_ACCUMULATOR" >> "$GITHUB_OUTPUT"
7070
echo "EOF" >> "$GITHUB_OUTPUT"
7171
exit 1
7272
fi
7373
74-
HEAD_COMMIT_SHA=$(echo "$HEAD_COMMIT_DETAILS_JSON" | jq -r '.sha')
75-
HEAD_COMMIT_DATE=$(echo "$HEAD_COMMIT_DETAILS_JSON" | jq -r '.commit.committer.date')
7674
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s Linux kernel master HEAD: \`%s\` (as of %s)\n\n" \
7775
"$PR_COMMENT_BODY_ACCUMULATOR" "$HEAD_COMMIT_SHA" "$HEAD_COMMIT_DATE"
7876
@@ -114,32 +112,24 @@ jobs:
114112
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s Found upstream Linux hash to check for fixes: \`%s\`\n" \
115113
"$PR_COMMENT_BODY_ACCUMULATOR" "$UPSTREAM_LINUX_HASH"
116114
117-
# --- Fetch the commit date of the UPSTREAM_LINUX_HASH from the Linux kernel repo ---
118-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s Fetching details for upstream Linux commit \`%s\` to get its date...\n" \
115+
# --- Get commit date of the UPSTREAM_LINUX_HASH from the cloned Linux kernel repo ---
116+
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s Getting commit date for upstream Linux commit \`%s\` from local bare clone...\n" \
119117
"$PR_COMMENT_BODY_ACCUMULATOR" "$UPSTREAM_LINUX_HASH"
120118
121-
UPSTREAM_COMMIT_DETAILS_JSON=$(curl -sS -H "Accept: application/vnd.github.v3+json" \
122-
-H "Authorization: token $GITHUB_TOKEN" \
123-
"https://api.github.com/repos/${LINUX_KERNEL_REPO_OWNER}/${LINUX_KERNEL_REPO_NAME}/commits/${UPSTREAM_LINUX_HASH}")
124-
125-
ERROR_MESSAGE=$(echo "$UPSTREAM_COMMIT_DETAILS_JSON" | jq -r 'if type == "object" and .message then .message else null end')
126-
if [ "$ERROR_MESSAGE" != "null" ] && [ -n "$ERROR_MESSAGE" ]; then
127-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s ERROR: Could not retrieve details or commit date for upstream hash \`%s\` from Linux kernel repo: %s\n" \
128-
"$PR_COMMENT_BODY_ACCUMULATOR" "$UPSTREAM_LINUX_HASH" "$ERROR_MESSAGE"
129-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s API Response snippet: %s\n" \
130-
"$PR_COMMENT_BODY_ACCUMULATOR" "$(echo "$UPSTREAM_COMMIT_DETAILS_JSON" | head -n 5)"
131-
echo "PR_COMMENT_BODY<<EOF" >> "$GITHUB_OUTPUT"
132-
echo "$PR_COMMENT_BODY_ACCUMULATOR" >> "$GITHUB_OUTPUT"
133-
echo "EOF" >> "$GITHUB_OUTPUT"
134-
exit 1
119+
# Check if the upstream hash exists in the local clone first
120+
if ! git -C linux.git cat-file -e "$UPSTREAM_LINUX_HASH"; then
121+
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s ERROR: Upstream commit \`%s\` not found in the local Linux kernel bare clone. This might indicate an invalid or very old hash.\n" \
122+
"$PR_COMMENT_BODY_ACCUMULATOR" "$UPSTREAM_LINUX_HASH"
123+
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s\n" "$PR_COMMENT_BODY_ACCUMULATOR"
124+
continue # Continue to the next PR commit
135125
fi
136-
UPSTREAM_COMMIT_DATE=$(echo "$UPSTREAM_COMMIT_DETAILS_JSON" | jq -r '.commit.committer.date')
137126
138-
if [ "$UPSTREAM_COMMIT_DATE" == "null" ] || [ -z "$UPSTREAM_COMMIT_DATE" ]; then
139-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s ERROR: Upstream commit \`%s\` found, but its date could not be extracted.\n" \
127+
# Get committer date in ISO 8601 format for `git log --since`
128+
UPSTREAM_COMMIT_DATE=$(git -C linux.git show -s --format=%cI "$UPSTREAM_LINUX_HASH")
129+
130+
if [ -z "$UPSTREAM_COMMIT_DATE" ]; then
131+
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s ERROR: Upstream commit \`%s\` found, but its date could not be extracted from local clone.\n" \
140132
"$PR_COMMENT_BODY_ACCUMULATOR" "$UPSTREAM_LINUX_HASH"
141-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s API Response snippet: %s\n" \
142-
"$PR_COMMENT_BODY_ACCUMULATOR" "$(echo "$UPSTREAM_COMMIT_DETAILS_JSON" | head -n 5)"
143133
echo "PR_COMMENT_BODY<<EOF" >> "$GITHUB_OUTPUT"
144134
echo "$PR_COMMENT_BODY_ACCUMULATOR" >> "$GITHUB_OUTPUT"
145135
echo "EOF" >> "$GITHUB_OUTPUT"
@@ -148,77 +138,74 @@ jobs:
148138
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s Upstream commit \`%s\` date: %s\n" \
149139
"$PR_COMMENT_BODY_ACCUMULATOR" "$UPSTREAM_LINUX_HASH" "$UPSTREAM_COMMIT_DATE"
150140
151-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s Searching for upstream commits on 'master' branch between \`%s\` and \`%s\` that fix \`%s\`...\n" \
141+
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s Searching for upstream commits on 'master' branch between \`%s\` and \`%s\` that fix \`%s\` using \`git log\`...\n" \
152142
"$PR_COMMENT_BODY_ACCUMULATOR" "$UPSTREAM_COMMIT_DATE" "$HEAD_COMMIT_DATE" "$UPSTREAM_LINUX_HASH"
153143
154144
FOUND_FIXING_COMMITS=()
155-
PAGE=1
156-
157-
# Loop to fetch all relevant commits between the target commit's date and HEAD's date
158-
while [ "$PAGE" -le "$MAX_PAGES_TO_FETCH" ]; do # Safeguard against infinite loops for extremely old commits
159-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s Fetching upstream Linux commits (page %d)...\n" \
160-
"$PR_COMMENT_BODY_ACCUMULATOR" "$PAGE"
161-
162-
CURRENT_PAGE_COMMITS_JSON=$(curl -sS -H "Accept: application/vnd.github.v3+json" \
163-
-H "Authorization: token $GITHUB_TOKEN" \
164-
"https://api.github.com/repos/${LINUX_KERNEL_REPO_OWNER}/${LINUX_KERNEL_REPO_NAME}/commits?sha=master&since=${UPSTREAM_COMMIT_DATE}&until=${HEAD_COMMIT_DATE}&per_page=100&page=$PAGE")
165-
166-
API_ERROR=$(echo "$CURRENT_PAGE_COMMITS_JSON" | jq -r 'if type == "object" and .message then .message else null end')
167-
if [ "$API_ERROR" != "null" ] && [ -n "$API_ERROR" ]; then
168-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s ERROR: Failed to retrieve subsequent upstream commits (page %d): %s\n" \
169-
"$PR_COMMENT_BODY_ACCUMULATOR" "$PAGE" "$API_ERROR"
170-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s API Response snippet: %s\n" \
171-
"$PR_COMMENT_BODY_ACCUMULATOR" "$(echo "$CURRENT_PAGE_COMMITS_JSON" | head -n 5)"
172-
echo "PR_COMMENT_BODY<<EOF" >> "$GITHUB_OUTPUT"
173-
echo "$PR_COMMENT_BODY_ACCUMULATOR" >> "$GITHUB_OUTPUT"
174-
echo "EOF" >> "$GITHUB_OUTPUT"
175-
exit 1
145+
# Construct the grep pattern using the first 12 characters of the SHA, commonly used in Fixes: tags in Linux kernel.
146+
UPSTREAM_LINUX_HASH_SHORT=$(echo "$UPSTREAM_LINUX_HASH" | cut -c 1-12)
147+
GREP_PATTERN="Fixes: ${UPSTREAM_LINUX_HASH_SHORT}"
148+
149+
# Use git log to find commits that mention the short SHA in their message, after the original commit's date.
150+
# --pretty=format:"%H%n%B" ensures SHA on one line, followed by the full message.
151+
GIT_LOG_OUTPUT=$(git -C linux.git log master \
152+
--since="${UPSTREAM_COMMIT_DATE}" \
153+
--until="${HEAD_COMMIT_DATE}" \
154+
--grep="${GREP_PATTERN}" \
155+
--pretty=format:"%H%n%B" \
156+
--regexp-ignore-case) # Use --regexp-ignore-case for case-insensitive grep
157+
158+
if [ -z "$GIT_LOG_OUTPUT" ]; then
159+
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s No upstream fixes found for \`%s\` in the specified range.\n" \
160+
"$PR_COMMENT_BODY_ACCUMULATOR" "$UPSTREAM_LINUX_HASH"
161+
else
162+
# Process the git log output line by line to parse SHAs and full messages.
163+
# Then, perform a more precise check for the full SHA in the "Fixes:" line.
164+
current_commit_sha=""
165+
commit_message_lines=()
166+
# Read the git log output, handling multi-line messages
167+
while IFS= read -r line; do
168+
if [[ "$line" =~ ^[0-9a-f]{40}$ ]]; then
169+
# This line is a SHA, indicating a new commit.
170+
# Process the previous commit's message (if any) before starting a new one.
171+
if [ -n "$current_commit_sha" ]; then
172+
FULL_MESSAGE=$(printf "%s\n" "${commit_message_lines[@]}")
173+
if echo "$FULL_MESSAGE" | grep -Eq "^Fixes: [0-9a-fA-F]*${UPSTREAM_LINUX_HASH}.*"; then
174+
FIX_MESSAGE_SNIPPET=$(echo "$FULL_MESSAGE" | grep -Ei "^Fixes:.*${UPSTREAM_LINUX_HASH}.*")
175+
FOUND_FIXING_COMMITS+=("${current_commit_sha}:${FIX_MESSAGE_SNIPPET}")
176+
fi
177+
fi
178+
current_commit_sha="$line"
179+
commit_message_lines=() # Reset message lines for the new commit
180+
else
181+
# This line is part of the current commit's message
182+
commit_message_lines+=("$line")
183+
fi
184+
done <<< "$GIT_LOG_OUTPUT"
185+
186+
# Process the last commit in the output
187+
if [ -n "$current_commit_sha" ]; then
188+
FULL_MESSAGE=$(printf "%s\n" "${commit_message_lines[@]}")
189+
if echo "$FULL_MESSAGE" | grep -Eq "^Fixes: [0-9a-fA-F]*${UPSTREAM_LINUX_HASH}.*"; then
190+
FIX_MESSAGE_SNIPPET=$(echo "$FULL_MESSAGE" | grep -Ei "^Fixes:.*${UPSTREAM_LINUX_HASH}.*")
191+
FOUND_FIXING_COMMITS+=("${current_commit_sha}:${FIX_MESSAGE_SNIPPET}")
192+
fi
176193
fi
177194
178-
CURRENT_PAGE_COUNT=$(echo "$CURRENT_PAGE_COMMITS_JSON" | jq 'length')
179-
if [ "$CURRENT_PAGE_COUNT" -eq 0 ]; then
180-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s No more subsequent upstream commits found within the date range. Stopping search.\n" \
181-
"$PR_COMMENT_BODY_ACCUMULATOR"
182-
break
195+
if [ ${#FOUND_FIXING_COMMITS[@]} -gt 0 ]; then
196+
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s SUCCESS: Found %d upstream Linux commit(s) that fix \`%s\`:\n" \
197+
"$PR_COMMENT_BODY_ACCUMULATOR" ${#FOUND_FIXING_COMMITS[@]} "$UPSTREAM_LINUX_HASH"
198+
for FIX_COMMIT_ENTRY in "${FOUND_FIXING_COMMITS[@]}"; do
199+
# Split SHA and message part for display
200+
FIX_COMMIT_SHA=$(echo "$FIX_COMMIT_ENTRY" | cut -d ':' -f 1)
201+
FIX_MESSAGE_SNIPPET=$(echo "$FIX_COMMIT_ENTRY" | cut -d ':' -f 2-) # Get everything after the first colon
202+
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s - \`%s\` (Fixes tag: \`%s\`)\n" \
203+
"$PR_COMMENT_BODY_ACCUMULATOR" "$FIX_COMMIT_SHA" "$FIX_MESSAGE_SNIPPET"
204+
done
205+
else
206+
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s No upstream fixes found for \`%s\` in the specified range.\n" \
207+
"$PR_COMMENT_BODY_ACCUMULATOR" "$UPSTREAM_LINUX_HASH"
183208
fi
184-
185-
# Iterate through each commit object on the current page, extracting SHA and message directly.
186-
echo "$CURRENT_PAGE_COMMITS_JSON" | jq -c '.[]' | while read -r commit_json_line; do
187-
COMMIT_SHA=$(echo "$commit_json_line" | jq -r '.sha')
188-
COMMIT_MESSAGE=$(echo "$commit_json_line" | jq -r '.commit.message')
189-
190-
# Skip the commit itself if it appears in the date range
191-
if [ "$COMMIT_SHA" = "$UPSTREAM_LINUX_HASH" ]; then
192-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s Skipping self-reference check for commit \`%s\`.\n" \
193-
"$PR_COMMENT_BODY_ACCUMULATOR" "$COMMIT_SHA"
194-
continue
195-
fi
196-
197-
# Check if this upstream commit's message contains the "Fixes:" tag for our hash.
198-
# Use the full SHA for matching, as it's definitive.
199-
if echo "$COMMIT_MESSAGE" | grep -Eq "^Fixes: [0-9a-fA-F]*${UPSTREAM_LINUX_HASH}.*"; then
200-
# Extract the specific "Fixes:" line for display
201-
FIX_MESSAGE_SNIPPET=$(echo "$COMMIT_MESSAGE" | grep -Ei "^Fixes:.*${UPSTREAM_LINUX_HASH}.*")
202-
FOUND_FIXING_COMMITS+=("$COMMIT_SHA:$FIX_MESSAGE_SNIPPET")
203-
fi
204-
done # End of while read loop
205-
206-
PAGE=$((PAGE + 1))
207-
done # End of while true loop for pages
208-
209-
if [ ${#FOUND_FIXING_COMMITS[@]} -gt 0 ]; then
210-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s SUCCESS: Found %d upstream Linux commit(s) that fix \`%s\`:\n" \
211-
"$PR_COMMENT_BODY_ACCUMULATOR" ${#FOUND_FIXING_COMMITS[@]} "$UPSTREAM_LINUX_HASH"
212-
for FIX_COMMIT_ENTRY in "${FOUND_FIXING_COMMITS[@]}"; do
213-
# Split SHA and message part for display
214-
FIX_COMMIT_SHA=$(echo "$FIX_COMMIT_ENTRY" | cut -d ':' -f 1)
215-
FIX_MESSAGE_SNIPPET=$(echo "$FIX_COMMIT_ENTRY" | cut -d ':' -f 2-) # Get everything after the first colon
216-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s - \`%s\` (Fixes tag: \`%s\`)\n" \
217-
"$PR_COMMENT_BODY_ACCUMULATOR" "$FIX_COMMIT_SHA" "$FIX_MESSAGE_SNIPPET"
218-
done
219-
else
220-
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s No upstream fixes found for \`%s\`.\n" \
221-
"$PR_COMMENT_BODY_ACCUMULATOR" "$UPSTREAM_LINUX_HASH"
222209
fi
223210
printf -v PR_COMMENT_BODY_ACCUMULATOR "%s\n" "$PR_COMMENT_BODY_ACCUMULATOR"
224211
done # End of for PR_COMMIT_SHA loop

0 commit comments

Comments
 (0)