Skip to content

Commit

Permalink
Merge branch 'tianocore:master' into arm-virt-psci-on-armmonitorlib
Browse files Browse the repository at this point in the history
  • Loading branch information
ardbiesheuvel committed Jul 25, 2024
2 parents 3c433e6 + 556640b commit deb9fef
Show file tree
Hide file tree
Showing 5 changed files with 277 additions and 5 deletions.
187 changes: 187 additions & 0 deletions .github/scripts/GitHub.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
## @file
# GitHub API helper functions.
#
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent
#

import logging
import re
import requests

from collections import OrderedDict
from edk2toollib.utility_functions import RunCmd, RunPythonScript
from io import StringIO
from typing import List

"""GitHub API helper functions."""


def leave_pr_comment(
token: str, owner: str, repo: str, pr_number: str, comment_body: str
):
"""Leaves a comment on a PR.
Args:
token (str): The GitHub token to use for authentication.
owner (str): The GitHub owner (organization) name.
repo (str): The GitHub repository name (e.g. 'edk2').
pr_number (str): The pull request number.
comment_body (str): The comment text. Markdown is supported.
"""
url = f"https://api.github.com/repos/{owner}/{repo}/issues/{pr_number}/comments"
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
}
data = {"body": comment_body}
response = requests.post(url, json=data, headers=headers)
response.raise_for_status()


def get_reviewers_for_current_branch(
workspace_path: str, maintainer_file_path: str, target_branch: str = "master"
) -> List[str]:
"""Get the reviewers for the current branch.
Args:
workspace_path (str): The workspace path.
maintainer_file_path (str): The maintainer file path.
target_branch (str, optional): The name of the target branch that the
current HEAD will merge to. Defaults to "master".
Returns:
List[str]: A list of GitHub usernames.
"""

commit_stream_buffer = StringIO()
cmd_ret = RunCmd(
"git",
f"log --format=format:%H {target_branch}..HEAD",
workingdir=workspace_path,
outstream=commit_stream_buffer,
logging_level=logging.INFO,
)
if cmd_ret != 0:
print(
f"::error title=Commit Lookup Error!::Error getting branch commits: [{cmd_ret}]: {commit_stream_buffer.getvalue()}"
)
return []

raw_reviewers = []
for commit_sha in commit_stream_buffer.getvalue().splitlines():
reviewer_stream_buffer = StringIO()
cmd_ret = RunPythonScript(
maintainer_file_path,
f"-g {commit_sha}",
workingdir=workspace_path,
outstream=reviewer_stream_buffer,
logging_level=logging.INFO,
)
if cmd_ret != 0:
print(
f"::error title=Reviewer Lookup Error!::Error calling GetMaintainer.py: [{cmd_ret}]: {reviewer_stream_buffer.getvalue()}"
)
return []

commit_reviewers = reviewer_stream_buffer.getvalue()

pattern = r"\[(.*?)\]"
matches = re.findall(pattern, commit_reviewers)
if not matches:
return []

print(
f"::debug title=Commit {commit_sha[:7]} Reviewer(s)::{', '.join(matches)}"
)

raw_reviewers.extend(matches)

reviewers = list(OrderedDict.fromkeys([r.strip() for r in raw_reviewers]))

print(f"::debug title=Total Reviewer Set::{', '.join(reviewers)}")

return reviewers


def download_gh_file(github_url: str, local_path: str, token=None):
"""Downloads a file from GitHub.
Args:
github_url (str): The GitHub raw file URL.
local_path (str): A local path to write the file contents to.
token (_type_, optional): A GitHub authentication token.
Only needed for a private repo. Defaults to None.
"""
headers = {}
if token:
headers["Authorization"] = f"Bearer {token}"

try:
response = requests.get(github_url, headers=headers)
response.raise_for_status()
except requests.exceptions.HTTPError:
print(
f"::error title=HTTP Error!::Error downloading {github_url}: {response.reason}"
)
return

with open(local_path, "w", encoding="utf-8") as file:
file.write(response.text)


def add_reviewers_to_pr(
token: str, owner: str, repo: str, pr_number: str, user_names: List[str]
):
"""Adds the set of GitHub usernames as reviewers to the PR.
Args:
token (str): The GitHub token to use for authentication.
owner (str): The GitHub owner (organization) name.
repo (str): The GitHub repository name (e.g. 'edk2').
pr_number (str): The pull request number.
user_names (List[str]): List of GitHub usernames to add as reviewers.
"""
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
}
pr_author_url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}"
url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}/requested_reviewers"

response = requests.get(pr_author_url, headers=headers)
if response.status_code != 200:
print(f"::error title=HTTP Error!::Error getting PR author: {response.reason}")
return
pr_author = response.json().get("user").get("login").strip()
while pr_author in user_names:
user_names.remove(pr_author)
data = {"reviewers": user_names}
response = requests.post(url, json=data, headers=headers)
try:
response.raise_for_status()
except requests.exceptions.HTTPError:
if (
response.status_code == 422
and "Reviews may only be requested from collaborators"
in response.json().get("message")
):
print(
f"::error title=User is not a Collaborator!::{response.json().get('message')}"
)
leave_pr_comment(
token,
owner,
repo,
pr_number,
f"⚠ **WARNING: Cannot add reviewers**: A user specified as a "
f"reviewer for this PR is not a collaborator "
f"of the edk2 repository. Please add them as a collaborator to the "
f"repository and re-request the review.\n\n"
f"Users requested:\n{', '.join(user_names)}",
)
elif response.status_code == 422:
print(
"::error title=Invalid Request!::The request is invalid. "
"Verify the API request string."
)
73 changes: 73 additions & 0 deletions .github/workflows/request-reviews.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@

# This workflow automatically adds the appropriate reviewers to a pull request.
#
# The workflow directly reuses logic in the BaseTools/Scripts/GetMaintainer.py script
# to determine the appropriate reviewers, so it matches what a user would see running
# the script locally.
#
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent

name: Add Pull Request Reviewers

on:
pull_request:
branches:
- master
types: [opened, ready_for_review, reopened, synchronize]

env:
GET_MAINTAINER_REL_PATH: "BaseTools/Scripts/GetMaintainer.py"

jobs:
auto-request-review:
name: Add Pull Request Reviewers
# Do not run on draft PRs and only run on PRs in the tianocore organization
if: ${{ github.event.pull_request.draft == false && github.repository_owner == 'tianocore' }}
runs-on: ubuntu-latest

permissions:
contents: read
issues: write
pull-requests: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'

- name: Install PIP Modules
run: pip install edk2-pytool-library edk2-pytool-extensions requests

- name: Add Reviewers to Pull Request
shell: python
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ORG_NAME: ${{ github.repository_owner }}
PR_NUMBER: ${{ github.event.number}}
REPO_NAME: ${{ github.event.pull_request.base.repo.name }}
TARGET_BRANCH: ${{ github.event.pull_request.base.ref }}
WORKSPACE_PATH: ${{ github.workspace }}
run: |
import os
import sys
sys.path.append(os.path.join(os.environ['WORKSPACE_PATH'], ".github"))
from scripts import GitHub
WORKSPACE_PATH = os.environ['WORKSPACE_PATH']
GET_MAINTAINER_LOCAL_PATH = os.path.join(WORKSPACE_PATH, os.environ['GET_MAINTAINER_REL_PATH'])
reviewers = GitHub.get_reviewers_for_current_branch(WORKSPACE_PATH, GET_MAINTAINER_LOCAL_PATH, f"origin/{os.environ['TARGET_BRANCH']}")
if not reviewers:
print("::notice title=No Reviewers Found!::No reviewers found for this PR.")
sys.exit(1)
print(f"::notice title=Reviewer List::Reviewers found for PR {os.environ['PR_NUMBER']}:\n{', '.join(reviewers)}")
GitHub.add_reviewers_to_pr(os.environ['GH_TOKEN'], os.environ['ORG_NAME'], os.environ['REPO_NAME'], os.environ['PR_NUMBER'], reviewers)
11 changes: 9 additions & 2 deletions BaseTools/Scripts/GetMaintainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ def get_modified_files(repo, args):
PARSER.add_argument('-l', '--lookup',
help='Find section matches for path LOOKUP',
required=False)
PARSER.add_argument('-g', '--github',
action='store_true',
help='Include GitHub usernames in output',
required=False)
ARGS = PARSER.parse_args()

REPO = SetupGit.locate_repo()
Expand All @@ -203,5 +207,8 @@ def get_modified_files(repo, args):

for address in ADDRESSES:
if '<' in address and '>' in address:
address = address.split('>', 1)[0] + '>'
print(' %s' % address)
address, github_id = address.split('>', 1)
address = address + '>'
github_id = github_id.strip() if ARGS.github else ''

print(' %s %s' % (address, github_id))
7 changes: 6 additions & 1 deletion PrmPkg/PrmConfigDxe/PrmConfigDxe.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,15 @@ SetRuntimeMemoryRangeAttributes (
continue;
}

// The memory space descriptor access attributes are not accurate. Don't pass
// in access attributes so SetMemorySpaceAttributes() doesn't update them.
// EFI_MEMORY_RUNTIME is not a CPU arch attribute, so calling
// SetMemorySpaceAttributes() with only it set will not clear existing page table
// attributes for this region, such as EFI_MEMORY_XP
Status = gDS->SetMemorySpaceAttributes (
RuntimeMmioRanges->Range[Index].PhysicalBaseAddress,
(UINT64)RuntimeMmioRanges->Range[Index].Length,
Descriptor.Attributes | EFI_MEMORY_RUNTIME
EFI_MEMORY_RUNTIME
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
Expand Down
4 changes: 2 additions & 2 deletions UefiCpuPkg/Library/MpInitLib/LoongArch64/MpLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ SortApicId (
} else {
for ( ; Index2 <= ApCount; Index2++) {
if (CpuInfoInHob[Index2].ApicId == INVALID_APIC_ID) {
CopyMem (&CpuInfoInHob[Index2], &CpuInfoInHob[Index1], sizeof (CPU_INFO_IN_HOB));
CpuMpData->CpuData[Index2] = CpuMpData->CpuData[Index1];
CopyMem (CpuInfoInHob + Index2, CpuInfoInHob + Index1, sizeof (CPU_INFO_IN_HOB));
CopyMem (CpuMpData->CpuData + Index2, CpuMpData->CpuData + Index1, sizeof (CPU_AP_DATA));
CpuInfoInHob[Index1].ApicId = INVALID_APIC_ID;
break;
}
Expand Down

0 comments on commit deb9fef

Please sign in to comment.