generated from actions/typescript-action
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
435 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import {getManagerConfig, RenovateConfig} from 'renovate/dist/config' | ||
import {getChangeLogJSON} from 'renovate/dist/workers/pr/changelog' | ||
import {UpdatedDependency, UpdatedDependencyWithChangelog} from './types' | ||
|
||
export async function fetchChangelogs( | ||
config: RenovateConfig, | ||
dependencies: UpdatedDependency[] | ||
): Promise<UpdatedDependencyWithChangelog[]> { | ||
const result: UpdatedDependencyWithChangelog[] = [] | ||
for (const updatedDependency of dependencies) { | ||
const {dependency, update, manager} = updatedDependency | ||
const logJSON = await getChangeLogJSON({ | ||
branchName: '', | ||
...getManagerConfig(config, manager), | ||
...dependency, | ||
...update | ||
}) | ||
|
||
result.push({...updatedDependency, changelog: logJSON}) | ||
} | ||
|
||
return result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import {PackageDependency} from 'renovate/dist/manager/types' | ||
import {ChangeLogResult} from 'renovate/dist/workers/pr/changelog' | ||
import {sanitizeMarkdown} from 'renovate/dist/util/markdown' | ||
import {UpdatedDependencyWithChangelog} from './types' | ||
|
||
export const commentTitle = '# Dependency updates summary' | ||
const footer = | ||
'\n---\n\nThis comment content is generated by [Renovate Bot](https://github.com/renovatebot/renovate)' | ||
|
||
export function getPrCommentBody( | ||
dependencies: UpdatedDependencyWithChangelog[] | ||
): string { | ||
const content = dependencies.map(getDependencyChangeContent) | ||
return `${commentTitle} | ||
This PR contains the following updates: | ||
<table> | ||
${content.map(x => x.tableRow).join('\n\n')} | ||
</table> | ||
--- | ||
### Release notes | ||
${content.map(x => x.changelog).join('\n\n')} | ||
${footer}` | ||
} | ||
|
||
function getDependencyChangeContent({ | ||
dependency, | ||
update, | ||
changelog | ||
}: UpdatedDependencyWithChangelog): {tableRow: string; changelog: string} { | ||
const dependencyLink = getDependencyNameLinked(dependency) | ||
const type = dependency.prettyDepType ?? dependency.depType | ||
const from = update.displayFrom ?? update.currentVersion | ||
const to = update.displayTo ?? update.newVersion | ||
|
||
const change = `<code>${from}</code> → <code>${to}</code>` | ||
|
||
return { | ||
tableRow: `<tr> | ||
<td>${dependencyLink}</td> | ||
<td>${type}</td> | ||
<td>${change}</td> | ||
</tr> | ||
`, | ||
changelog: `<details><summary>${dependency.depName}</summary> | ||
${getReleaseNotes(dependencyLink, changelog)}</details>` | ||
} | ||
} | ||
|
||
function getReleaseNotes( | ||
dependencyLink: string, | ||
changelog: ChangeLogResult | null | ||
): string { | ||
const releases = | ||
changelog?.versions?.map(x => { | ||
const versionWithPrefix = x.version.startsWith('v') | ||
? x.version | ||
: `v${x.version}` | ||
|
||
const header = x.releaseNotes | ||
? `### [\`${versionWithPrefix}\`](${x.releaseNotes.url})` | ||
: `### \`${versionWithPrefix}\`` | ||
|
||
return `${header} | ||
${x.compare.url ? `[Compare Source](${x.compare.url})` : ''} | ||
${x.releaseNotes?.body ?? ''}` | ||
}) ?? [] | ||
|
||
if (releases.length === 0) { | ||
return `<blockquote></p><p>No changelog found, please review changelog from official resources of ${dependencyLink}</blockquote>` | ||
} | ||
|
||
return sanitizeMarkdown(` | ||
<blockquote> | ||
<p></p> | ||
${releases.join('\n\n')} | ||
</blockquote>`) | ||
} | ||
|
||
function getDependencyNameLinked({ | ||
depName, | ||
homepage, | ||
sourceUrl, | ||
dependencyUrl, | ||
changelogUrl | ||
}: // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
PackageDependency & Record<string, any>): string { | ||
let depNameLinked = depName || '' | ||
const primaryLink = homepage || sourceUrl || dependencyUrl | ||
if (primaryLink) { | ||
depNameLinked = `<a href="${primaryLink}">${depNameLinked}</a>` | ||
} | ||
const otherLinks = [] | ||
if (homepage && sourceUrl) { | ||
otherLinks.push(`<a href="${sourceUrl}">source</a>`) | ||
} | ||
if (changelogUrl) { | ||
otherLinks.push(`<a href="${changelogUrl}">changelog</a>`) | ||
} | ||
if (otherLinks.length) { | ||
depNameLinked += ` (${otherLinks.join(', ')})` | ||
} | ||
|
||
return depNameLinked | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import {parseConfigs, RenovateConfig} from 'renovate/dist/config' | ||
import {setUtilConfig} from 'renovate/dist/util' | ||
import {getRepositoryConfig} from 'renovate/dist/workers/global' | ||
import {globalInitialize} from 'renovate/dist/workers/global/initialize' | ||
import {initRepo} from 'renovate/dist/workers/repository/init' | ||
|
||
export async function getRenovateConfig({ | ||
token, | ||
owner, | ||
repo | ||
}: { | ||
token: string | ||
owner: string | ||
repo: string | ||
}): Promise<RenovateConfig> { | ||
const globalConfig = await parseConfigs( | ||
{ | ||
...process.env, | ||
GITHUB_COM_TOKEN: token | ||
}, | ||
[ | ||
// this might prevent renovate from making changes to the repository | ||
'--dry-run', | ||
'true', | ||
// this prevents renovate from creating the onboarding branch | ||
'--onboarding', | ||
'false', | ||
// this prevents renovate from complaining that the onboarding branch does not exist | ||
'--require-config', | ||
'false', | ||
'--token', | ||
token | ||
] | ||
) | ||
|
||
// not sure if it's necessary, but it probably is, renovate uses this setting to use the locked version as the current version | ||
globalConfig.rangeStrategy = 'update-lockfile' | ||
// username and gitAuthor are only necessary for writing data, we only use Renovate to read data | ||
globalConfig.gitAuthor = | ||
'github-actions <41898282+github-actions[bot]@users.noreply.github.com>' | ||
globalConfig.username = 'github-actions[bot]' | ||
// otherwise renovate will only be able to work with branch with `renovate/` prefix | ||
globalConfig.branchPrefix = '' | ||
|
||
// this is necessary to get only one update from renovate, so we can just replace the latest version with the verion from the branch | ||
globalConfig.separateMajorMinor = false | ||
|
||
let config = await globalInitialize(globalConfig) | ||
|
||
config = await getRepositoryConfig(config, `${owner}/${repo}`) | ||
await setUtilConfig(config) | ||
|
||
return await initRepo(config) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import {PackageDependency, PackageFile} from 'renovate/dist/manager/types' | ||
import {UpdatedDependency} from './types' | ||
|
||
export function* getUpdatedDependencies( | ||
baseDependencies: Record<string, PackageFile[]>, | ||
headDependencies: Record<string, PackageFile[]> | ||
): IterableIterator<UpdatedDependency> { | ||
for (const managerName in baseDependencies) { | ||
const basePackageList = baseDependencies[managerName] | ||
const headPackageList = headDependencies[managerName] | ||
|
||
if ( | ||
!headPackageList || | ||
headPackageList.length === 0 || | ||
basePackageList.length === 0 | ||
) { | ||
continue | ||
} | ||
|
||
for (const basePackage of basePackageList) { | ||
const headPackage = headPackageList.find( | ||
x => x.packageFile === basePackage.packageFile | ||
) | ||
|
||
if (!headPackage) { | ||
// the package seems to be removed from the head | ||
continue | ||
} | ||
|
||
for (const baseDependency of basePackage.deps) { | ||
const headDependency = headPackage.deps.find( | ||
x => | ||
x.depName === baseDependency.depName && | ||
x.depType === baseDependency.depType | ||
) | ||
|
||
if (!headDependency) { | ||
// the dependency seems to be removed from the head | ||
continue | ||
} | ||
|
||
if (!isSameVersion(baseDependency, headDependency)) { | ||
if (!baseDependency.updates || baseDependency.updates.length === 0) { | ||
continue | ||
} | ||
|
||
const [update] = baseDependency.updates // there should be a single update because we `fetchUpdates` on the base and use the rangeStrategy of 'update-lockfile' | ||
yield { | ||
manager: managerName, | ||
packageFile: basePackage, | ||
update, | ||
dependency: baseDependency | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
function isSameVersion( | ||
a: PackageDependency<Record<string, unknown>>, | ||
b: PackageDependency<Record<string, unknown>> | ||
): boolean { | ||
if (a.lockedVersion && b.lockedVersion) { | ||
return a.lockedVersion === b.lockedVersion | ||
} | ||
|
||
return a.currentValue === b.currentValue | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import {ERROR, INFO, Stream, WARN} from 'bunyan' | ||
import {BunyanRecord} from 'renovate/dist/logger/utils' | ||
import * as core from '@actions/core' | ||
import {Writable} from 'stream' | ||
|
||
class GithubActionsStream extends Writable { | ||
constructor() { | ||
super({ | ||
objectMode: true | ||
}) | ||
} | ||
|
||
_write(rec: BunyanRecord, _: unknown, next: () => void): void { | ||
if (rec.level < INFO) { | ||
core.debug(rec.msg) | ||
} else if (rec.level < WARN) { | ||
core.info(rec.msg) | ||
} else if (rec.level < ERROR) { | ||
core.warning(rec.msg) | ||
} else { | ||
core.error(rec.msg) | ||
} | ||
|
||
next() | ||
} | ||
} | ||
|
||
export function createGithubActionsBunyanStream(): Stream { | ||
return { | ||
name: 'github-actions', | ||
level: 'debug', | ||
stream: new GithubActionsStream(), | ||
type: 'raw' | ||
} | ||
} |
Oops, something went wrong.