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