Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yifeng/nova adapter config change #67

Closed
wants to merge 44 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
7020f09
Merging from master (#40)
Peiling-Ding Jul 6, 2023
9fceb85
implement file fetcher for stored_response (#43)
shunj-nb Jul 7, 2023
f7f0e0d
add error message (#45)
shunj-nb Jul 7, 2023
987c622
Peiling/feature/plugin (#47)
Peiling-Ding Jul 14, 2023
46da2b7
Fix: deal tiers no longer ignored due to presence of tid (#2829)
bsardo Jun 28, 2023
7ccaeba
CAPT-787: GPP support for imds bidder. (#2867)
ecammit Jun 29, 2023
c3db838
Adsinteractive: change usersync endpoint to https (#2861)
balintvargha Jun 29, 2023
bfb4005
consumable adapter: add gpp support (#2883)
jpiros Jun 30, 2023
cc1dc07
feat: IX Bid Adapter - gpp support for user sync urls (#2873)
ccorbo Jun 30, 2023
5ac708b
fix: update links in readme (#2888)
akkapur Jul 3, 2023
f68fd5a
New Adapter: AIDEM (#2824)
gsollazzo Jul 5, 2023
69969f9
Improve Digital adapter: Set currency in bid response (#2886)
jbartek25 Jul 5, 2023
d893f4c
Sharethrough: Support multiformat bid request impression (#2866)
maxime-dupuis Jul 5, 2023
c2b49bb
Triplelift Bid Adapter: Adding GPP Support (#2887)
patrickloughrey Jul 5, 2023
0470ca7
YahooAdvertising rebranding to Yahoo Ads. (#2872)
radubarbos Jul 5, 2023
72a0c28
IX: MultiImp Implementation (#2779)
ccorbo Jul 5, 2023
2dcd4ed
Exchange unit test fix (#2868)
VeronikaSolovei9 Jul 5, 2023
cf5e688
Semgrep rules for adapters (#2833)
onkarvhanumante Jul 6, 2023
a916285
IX: Remove glog statement (#2909)
bsardo Jul 6, 2023
42a10d1
Activities framework (#2844)
VeronikaSolovei9 Jul 6, 2023
02f40e3
PWBID: Update Default Endpoint (#2903)
GLStephen Jul 7, 2023
9df856d
script to run semgrep tests against adapter PRs (#2907)
onkarvhanumante Jul 10, 2023
195af40
semgrep rule to detect undesirable package imports in adapter code (#…
onkarvhanumante Jul 10, 2023
7a25e69
update package-import message (#2913)
onkarvhanumante Jul 10, 2023
345168a
Peiling/chore/sync to v0.263.0 (#48)
Peiling-Ding Jul 14, 2023
bae76c1
Merge remote-tracking branch 'origin/msp' into msp
Peiling-Ding Jul 14, 2023
b0888c6
Bump google.golang.org/grpc from 1.46.2 to 1.53.0 (#2905)
dependabot[bot] Jul 10, 2023
fae7e0e
Load Bidders through Plugins (#50)
Peiling-Ding Aug 2, 2023
7e7b3c9
add adapter nova (#51)
shunj-nb Sep 19, 2023
57f7c83
enforce fb bid floor (#52)
shunj-nb Oct 17, 2023
ec5c7e5
fix floor check bug (#53)
shunj-nb Oct 17, 2023
5296c2c
Add adapters to support facebook multicall (#54)
Peiling-Ding Oct 24, 2023
573c6f6
Add nova multicall (#55)
Peiling-Ding Nov 8, 2023
7505e08
ad cache (#56)
shunj-nb Dec 22, 2023
80fc15f
Load bidder based on so_path (#57)
Peiling-Ding Feb 21, 2024
dd7250a
cherry pick rise placement update (#58)
shunj-nb Apr 25, 2024
798a249
msb peek version (#59)
shunj-nb Apr 30, 2024
a5319d0
fb dyn config (#60)
shunj-nb Jun 7, 2024
bf13ce3
Update proto version (#61)
Peiling-Ding Jun 21, 2024
079ec90
increase prometheus histogram buckets (#62)
shunj-nb Aug 2, 2024
f600f3f
mf multi-format test (#63)
shunj-nb Sep 12, 2024
4ecd103
Integrating Prometheus Metrics on MSP side (#64)
ashhadal Sep 16, 2024
9f7f1da
Refactor server code (#66)
ashhadal Sep 18, 2024
e42965e
adding new config info for nova
YifengW86 Sep 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
337 changes: 337 additions & 0 deletions .github/workflows/helpers/pull-request-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,337 @@
const synchronizeEvent = "synchronize",
openedEvent = "opened",
completedStatus = "completed",
resultSize = 100

class diffHelper {
constructor(input) {
this.owner = input.context.repo.owner
this.repo = input.context.repo.repo
this.github = input.github
this.pullRequestNumber = input.context.payload.pull_request.number
this.pullRequestEvent = input.event
this.testName = input.testName
this.fileNameFilter = !input.fileNameFilter ? () => true : input.fileNameFilter
this.fileLineFilter = !input.fileLineFilter ? () => true : input.fileLineFilter
}

/*
Checks whether the test defined by this.testName has been executed on the given commit
@param {string} commit - commit SHA to check for test execution
@returns {boolean} - returns true if the test has been executed on the commit, otherwise false
*/
async #isTestExecutedOnCommit(commit) {
const response = await this.github.rest.checks.listForRef({
owner: this.owner,
repo: this.repo,
ref: commit,
})

return response.data.check_runs.some(
({ status, name }) => status === completedStatus && name === this.testName
)
}

/*
Retrieves the line numbers of added or updated lines in the provided files
@param {Array} files - array of files containing their filename and patch
@returns {Object} - object mapping filenames to arrays of line numbers indicating the added or updated lines
*/
async #getDiffForFiles(files = []) {
let diff = {}
for (const { filename, patch } of files) {
if (this.fileNameFilter(filename)) {
const lines = patch.split("\n")
if (lines.length === 1) {
continue
}

let lineNumber
for (const line of lines) {
// Check if line is diff header
// example:
// @@ -1,3 +1,3 @@
// 1 var a
// 2
// 3 - //test
// 3 +var b
// Here @@ -1,3 +1,3 @@ is diff header
if (line.match(/@@\s.*?@@/) != null) {
lineNumber = parseInt(line.match(/\+(\d+)/)[0])
continue
}

// "-" prefix indicates line was deleted. So do not consider deleted line
if (line.startsWith("-")) {
continue
}

// "+"" prefix indicates line was added or updated. Include line number in diff details
if (line.startsWith("+") && this.fileLineFilter(line)) {
diff[filename] = diff[filename] || []
diff[filename].push(lineNumber)
}
lineNumber++
}
}
}
return diff
}

/*
Retrieves a list of commits that have not been checked by the test defined by this.testName
@returns {Array} - array of commit SHAs that have not been checked by the test
*/
async #getNonScannedCommits() {
const { data } = await this.github.rest.pulls.listCommits({
owner: this.owner,
repo: this.repo,
pull_number: this.pullRequestNumber,
per_page: resultSize,
})
let nonScannedCommits = []

// API returns commits in ascending order. Loop in reverse to quickly retrieve unchecked commits
for (let i = data.length - 1; i >= 0; i--) {
const { sha, parents } = data[i]

// Commit can be merged master commit. Such commit have multiple parents
// Do not consider such commit for building file diff
if (parents.length > 1) {
continue
}

const isTestExecuted = await this.#isTestExecutedOnCommit(sha)
if (isTestExecuted) {
// Remaining commits have been tested in previous scans. Therefore, do not need to be considered again
break
} else {
nonScannedCommits.push(sha)
}
}

// Reverse to return commits in ascending order. This is needed to build diff for commits in chronological order
return nonScannedCommits.reverse()
}

/*
Filters the commit diff to include only the files that are part of the PR diff
@param {Array} commitDiff - array of line numbers representing lines added or updated in the commit
@param {Array} prDiff - array of line numbers representing lines added or updated in the pull request
@returns {Array} - filtered commit diff, including only the files that are part of the PR diff
*/
async #filterCommitDiff(commitDiff = [], prDiff = []) {
return commitDiff.filter((file) => prDiff.includes(file))
}

/*
Builds the diff for the pull request, including both the changes in the pull request and the changes in non-scanned commits
@returns {string} - json string representation of the pull request diff and the diff for non-scanned commits
*/
async buildDiff() {
const { data } = await this.github.rest.pulls.listFiles({
owner: this.owner,
repo: this.repo,
pull_number: this.pullRequestNumber,
per_page: resultSize,
})

const pullRequestDiff = await this.#getDiffForFiles(data)

const nonScannedCommitsDiff =
Object.keys(pullRequestDiff).length != 0 && this.pullRequestEvent === synchronizeEvent // The "synchronize" event implies that new commit are pushed after the pull request was opened
? await this.getNonScannedCommitDiff(pullRequestDiff)
: {}

const prDiffFiles = Object.keys(pullRequestDiff)
const pullRequest = {
hasChanges: prDiffFiles.length > 0,
files: prDiffFiles.join(" "),
diff: pullRequestDiff,
}
const uncheckedCommits = { diff: nonScannedCommitsDiff }
return JSON.stringify({ pullRequest, uncheckedCommits })
}

/*
Retrieves the diff for non-scanned commits by comparing their changes with the pull request diff
@param {Object} pullRequestDiff - The diff of files in the pull request
@returns {Object} - The diff of files in the non-scanned commits that are part of the pull request diff
*/
async getNonScannedCommitDiff(pullRequestDiff) {
let nonScannedCommitsDiff = {}
// Retrieves list of commits that have not been scanned by the PR check
const nonScannedCommits = await this.#getNonScannedCommits()
for (const commit of nonScannedCommits) {
const { data } = await this.github.rest.repos.getCommit({
owner: this.owner,
repo: this.repo,
ref: commit,
})

const commitDiff = await this.#getDiffForFiles(data.files)
const files = Object.keys(commitDiff)
for (const file of files) {
// Consider scenario where the changes made to a file in the initial commit are completely undone by subsequent commits
// In such cases, the modifications from the initial commit should not be taken into account
// If the changes were entirely removed, there should be no entry for the file in the pullRequestStats
const filePRDiff = pullRequestDiff[file]
if (!filePRDiff) {
continue
}

// Consider scenario where changes made in the commit were partially removed or modified by subsequent commits
// In such cases, include only those commit changes that are part of the pullRequestStats object
// This ensures that only the changes that are reflected in the pull request are considered
const changes = await this.#filterCommitDiff(commitDiff[file], filePRDiff)

if (changes.length !== 0) {
// Check if nonScannedCommitsDiff[file] exists, if not assign an empty array to it
nonScannedCommitsDiff[file] = nonScannedCommitsDiff[file] || []
// Combine the existing nonScannedCommitsDiff[file] array with the commit changes
// Remove any duplicate elements using the Set data structure
nonScannedCommitsDiff[file] = [
...new Set([...nonScannedCommitsDiff[file], ...changes]),
]
}
}
}
return nonScannedCommitsDiff
}
}

class semgrepHelper {
constructor(input) {
this.owner = input.context.repo.owner
this.repo = input.context.repo.repo
this.github = input.github

this.pullRequestNumber = input.context.payload.pull_request.number
this.pullRequestEvent = input.event

this.pullRequestDiff = input.diff.pullRequest.diff
this.newCommitsDiff = input.diff.uncheckedCommits.diff

this.semgrepErrors = []
this.semgrepWarnings = []
input.semgrepResult.forEach((res) => {
res.severity === "High" ? this.semgrepErrors.push(res) : this.semgrepWarnings.push(res)
})

this.headSha = input.headSha
}

/*
Retrieves the matching line number from the provided diff for a given file and range of lines
@param {Object} range - object containing the file, start line, and end line to find a match
@param {Object} diff - object containing file changes and corresponding line numbers
@returns {number|null} - line number that matches the range within the diff, or null if no match is found
*/
async #getMatchingLineFromDiff({ file, start, end }, diff) {
const fileDiff = diff[file]
if (!fileDiff) {
return null
}
if (fileDiff.includes(start)) {
return start
}
if (fileDiff.includes(end)) {
return end
}
return null
}

/*
Splits the semgrep results into different categories based on the scan
@param {Array} semgrepResults - array of results reported by semgrep
@returns {Object} - object containing the categorized semgrep results i.e results reported in previous scans and new results found in the current scan
*/
async #splitSemgrepResultsByScan(semgrepResults = []) {
const result = {
nonDiff: [], // Errors or warnings found in files updated in pull request, but not part of sections that were modified in the pull request
previous: [], // Errors or warnings found in previous semgrep scans
current: [], // Errors or warnings found in current semgrep scan
}

for (const se of semgrepResults) {
const prDiffLine = await this.#getMatchingLineFromDiff(se, this.pullRequestDiff)
if (!prDiffLine) {
result.nonDiff.push({ ...se })
continue
}

switch (this.pullRequestEvent) {
case openedEvent:
// "Opened" event implies that this is the first check
// Therefore, the error should be appended to the result.current
result.current.push({ ...se, line: prDiffLine })
case synchronizeEvent:
const commitDiffLine = await this.#getMatchingLineFromDiff(se, this.newCommitsDiff)
// Check if error or warning is part of current commit diff
// If not then error or warning was reported in previous scans
commitDiffLine != null
? result.current.push({ ...se, line: commitDiffLine })
: result.previous.push({
...se,
line: prDiffLine,
})
}
}
return result
}

/*
Adds review comments based on the semgrep results to the current pull request
@returns {Object} - object containing the count of unaddressed comments from the previous scan and the count of new comments from the current scan
*/
async addReviewComments() {
let result = {
previousScan: { unAddressedComments: 0 },
currentScan: { newComments: 0 },
}

if (this.semgrepErrors.length == 0 && this.semgrepWarnings.length == 0) {
return result
}

const errors = await this.#splitSemgrepResultsByScan(this.semgrepErrors)
if (errors.previous.length == 0 && errors.current.length == 0) {
console.log("Semgrep did not find any errors in the current pull request changes")
} else {
for (const { message, file, line } of errors.current) {
await this.github.rest.pulls.createReviewComment({
owner: this.owner,
repo: this.repo,
pull_number: this.pullRequestNumber,
commit_id: this.headSha,
body: message,
path: file,
line: line,
})
}
result.currentScan.newComments = errors.current.length
if (this.pullRequestEvent == synchronizeEvent) {
result.previousScan.unAddressedComments = errors.previous.length
}
}

const warnings = await this.#splitSemgrepResultsByScan(this.semgrepWarnings)
for (const { message, file, line } of warnings.current) {
await this.github.rest.pulls.createReviewComment({
owner: this.owner,
repo: this.repo,
pull_number: this.pullRequestNumber,
commit_id: this.headSha,
body: "Consider this as a suggestion. " + message,
path: file,
line: line,
})
}
return result
}
}

module.exports = {
diffHelper: (input) => new diffHelper(input),
semgrepHelper: (input) => new semgrepHelper(input),
}
Loading
Loading