-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
devops: Add ci warning for swizzled docusaurus components #9467
Changes from 21 commits
9fe5c60
afd5505
4e158d2
82f66ec
438a1e6
8677c52
6354ba2
d16d987
7f9f94e
2a0573a
a1c24dd
5ccbb69
372d18f
c4a41f6
11fbd0b
da3cf2e
c77af69
db2e03c
81f020f
9e1c2e4
637d122
640567d
78551ff
5311d03
6f867f7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
name: 'docusaurus-theme-openapi swizzled component changes warning' | ||
description: 'Check for changes in docusaurus-theme-openapi components which are swizzled and prints out a warning' | ||
branding: | ||
icon: 'alert-triangle' | ||
color: 'yellow' | ||
inputs: | ||
github-token: | ||
description: 'The GITHUB_TOKEN secret' | ||
required: true | ||
runs: | ||
using: 'node16' | ||
main: 'index.js' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
'use strict' | ||
|
||
/** | ||
* Returns info about all files changed in a PR (max 3000 results) | ||
* | ||
* @param {object} client hydrated octokit ready to use for GitHub Actions | ||
* @param {string} owner repo owner | ||
* @param {string} repo repo name | ||
* @param {number} pullNumber pull request number | ||
* @returns {object[]} array of object that describe pr changed files - see https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#list-pull-requests-files | ||
*/ | ||
async function getAllFilesForPullRequest(client, owner, repo, pullNumber) { | ||
const perPage = 100 // Max number of items per page | ||
let page = 1 // Start with the first page | ||
let allFiles = [] | ||
while (true) { | ||
const response = await client.rest.pulls.listFiles({ | ||
owner, | ||
repo, | ||
pull_number: pullNumber, | ||
per_page: perPage, | ||
page, | ||
}) | ||
|
||
if (response.data.length === 0) { | ||
// Break the loop if no more results | ||
break | ||
} | ||
|
||
allFiles = allFiles.concat(response.data) | ||
page++ // Move to the next page | ||
} | ||
return allFiles | ||
} | ||
|
||
/** | ||
* Get a list of files changed betwen two tags for a github repo | ||
* | ||
* @param {object} client hydrated octokit ready to use for GitHub Actions | ||
* @param {string} owner repo owner | ||
* @param {string} repo repo name | ||
* @param {string} baseTag base tag | ||
* @param {string} headTag head tag | ||
* @returns {string[]} Array listing all changed files betwen the base tag and the head tag | ||
*/ | ||
async function getChangedFilesBetweenTags( | ||
client, | ||
owner, | ||
repo, | ||
baseTag, | ||
headTag, | ||
) { | ||
const response = await client.rest.repos.compareCommits({ | ||
owner, | ||
repo, | ||
base: baseTag, | ||
head: headTag, | ||
}) | ||
|
||
return response.data.files.map(file => file.filename) | ||
} | ||
|
||
function findKeyEndingWith(obj, ending) { | ||
for (const key in obj) { | ||
if (key.endsWith(ending)) { | ||
return key | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Get large (>1MB) JSON file from git repo on at ref as a json object | ||
* | ||
* @param {object} client Hydrated octokit ready to use for GitHub Actions | ||
* @param {string} owner Repo owner | ||
* @param {string} repo Repo name | ||
* @param {string} path Path of the file in repo relative to root directory | ||
* @param {string} ref Git refrence (commit, branch, tag) | ||
* @returns {string[]} Array listing all changed files betwen the base tag and the head tag | ||
*/ | ||
async function getLargeJsonAtRef(client, owner, repo, path, ref) { | ||
const fileSha = ( | ||
await client.rest.repos.getContent({ | ||
owner, | ||
repo, | ||
path, | ||
ref, | ||
}) | ||
).data.sha | ||
const fileBlob = ( | ||
await client.rest.git.getBlob({ | ||
owner, | ||
repo, | ||
file_sha: fileSha, | ||
}) | ||
).data.content | ||
return JSON.parse(Buffer.from(fileBlob, 'base64').toString()) | ||
} | ||
|
||
module.exports = { | ||
getAllFilesForPullRequest, | ||
getChangedFilesBetweenTags, | ||
findKeyEndingWith, | ||
getLargeJsonAtRef, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
'use strict' | ||
|
||
const core = require('@actions/core') | ||
const github = require('@actions/github') | ||
const { | ||
getAllFilesForPullRequest, | ||
getChangedFilesBetweenTags, | ||
findKeyEndingWith, | ||
getLargeJsonAtRef, | ||
} = require('./helpers') | ||
|
||
async function run() { | ||
try { | ||
const token = core.getInput('github-token', { required: true }) | ||
|
||
const { pull_request: pr } = github.context.payload | ||
if (!pr) { | ||
throw new Error('Event payload missing `pull_request`') | ||
} | ||
|
||
const client = github.getOctokit(token) | ||
const packageName = 'docusaurus-theme-openapi' | ||
const packageParentName = 'docusaurus-preset-openapi' | ||
const overideComponents = ['Curl', 'Response'] | ||
const messageTemplate = `<table><thead><tr><th colspan="2"> | ||
⚠️ This PR contains changes to components of ${packageName} we've overridden | ||
</th></tr> | ||
<tr><th colspan="2"> | ||
We need to watch out for changes to the ${overideComponents.join( | ||
', ', | ||
)} components | ||
</th></tr></thead> | ||
` | ||
|
||
if ( | ||
!['dependabot[bot]', 'dependabot-preview[bot]'].includes(pr.user.login) | ||
) { | ||
return | ||
} | ||
const files = await getAllFilesForPullRequest( | ||
client, | ||
github.context.repo.owner, | ||
github.context.repo.repo, | ||
pr.number, | ||
) | ||
|
||
const file = files.filter(f => f.filename === 'package-lock.json')[0] | ||
if (file === undefined) { | ||
return | ||
} | ||
|
||
const prCommitRefForFile = file.contents_url.split('ref=')[1] | ||
const pkgLockNewJson = await getLargeJsonAtRef( | ||
client, | ||
github.context.repo.owner, | ||
github.context.repo.repo, | ||
file.filename, | ||
prCommitRefForFile, | ||
) | ||
const pkgLockOldJson = await getLargeJsonAtRef( | ||
client, | ||
github.context.repo.owner, | ||
github.context.repo.repo, | ||
file.filename, | ||
'master', | ||
) | ||
|
||
const oldVesionModuleKey = findKeyEndingWith( | ||
pkgLockOldJson.packages, | ||
`node_modules/${packageName}`, | ||
) | ||
const newVesionModuleKey = findKeyEndingWith( | ||
pkgLockNewJson.packages, | ||
`node_modules/${packageName}`, | ||
) | ||
let oldVersion = pkgLockOldJson.packages[oldVesionModuleKey].version | ||
let newVersion = pkgLockNewJson.packages[newVesionModuleKey].version | ||
|
||
const oldVesionModuleKeyParent = findKeyEndingWith( | ||
pkgLockOldJson.packages, | ||
`node_modules/${packageParentName}`, | ||
) | ||
const newVesionModuleKeyParent = findKeyEndingWith( | ||
pkgLockNewJson.packages, | ||
`node_modules/${packageParentName}`, | ||
) | ||
const oldVersionParent = | ||
pkgLockOldJson.packages[oldVesionModuleKeyParent].dependencies[ | ||
packageName | ||
].substring(1) | ||
const newVersionParent = | ||
pkgLockNewJson.packages[newVesionModuleKeyParent].dependencies[ | ||
packageName | ||
].substring(1) | ||
|
||
// if parent dependency is higher version then existing | ||
// npm install will retrive the newer version from the parent dependency | ||
if (oldVersionParent > oldVersion) { | ||
oldVersion = oldVersionParent | ||
} | ||
if (newVersionParent > newVersion) { | ||
newVersion = newVersionParent | ||
} | ||
|
||
if (newVersion !== oldVersion) { | ||
const pkgChangedFiles = await getChangedFilesBetweenTags( | ||
client, | ||
'cloud-annotations', | ||
'docusaurus-openapi', | ||
`v${oldVersion}`, | ||
`v${newVersion}`, | ||
) | ||
const changedComponents = overideComponents.filter( | ||
componenet => | ||
pkgChangedFiles.filter( | ||
path => | ||
path.includes('docusaurus-theme-openapi/src/theme') && | ||
path.includes(componenet), | ||
).length > 0, | ||
) | ||
const versionReport = `<tbody><tr><td> Old version </td><td> ${oldVersion} </td></tr> | ||
<tr><td> New version </td><td> ${newVersion} </td></tr> | ||
` | ||
const changedComponentsReport = `<tr><td> Overide components changed </td><td> ${changedComponents.join( | ||
', ', | ||
)} </td></tr></tbody></table> | ||
` | ||
const body = messageTemplate + versionReport + changedComponentsReport | ||
await client.rest.issues.createComment({ | ||
owner: github.context.repo.owner, | ||
repo: github.context.repo.repo, | ||
issue_number: pr.number, | ||
body, | ||
}) | ||
|
||
core.debug('Found changes and posted comment, done.') | ||
return | ||
} | ||
|
||
core.debug('No changes found, done.') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we make these log statements use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. This would be easier to understand. |
||
} catch (error) { | ||
core.setFailed(error.message) | ||
} | ||
} | ||
|
||
run() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be useful here if we could write a log message here (again,
core.info()
) witholdVersion
andnewVersion
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added with 5311d03