2017-06-28 09:23:40 +00:00
const onboardPrTitle = 'Configure Renovate' ;
2017-06-26 12:26:49 +00:00
module . exports = {
2017-07-08 04:01:02 +00:00
isRepoPrivate ,
2017-06-28 09:23:40 +00:00
createBranch ,
ensurePr ,
2017-06-26 12:26:49 +00:00
getOnboardingStatus ,
} ;
2017-07-08 04:01:02 +00:00
async function isRepoPrivate ( config ) {
let repoIsPrivate = true ;
for ( const packageFile of config . packageFiles ) {
const fileName =
typeof packageFile === 'string' ? packageFile : packageFile . packageFile ;
const packageContent = await config . api . getFileJson ( fileName ) ;
repoIsPrivate = repoIsPrivate && packageContent && packageContent . private ;
}
return repoIsPrivate === true ;
}
2017-06-28 09:23:40 +00:00
async function createBranch ( config ) {
2017-09-14 05:21:22 +00:00
const { logger } = config ;
2017-08-04 06:32:22 +00:00
const onboardBranchName = ` ${ config . branchPrefix } configure ` ;
2017-07-08 04:01:02 +00:00
const repoIsPrivate = await module . exports . isRepoPrivate ( config ) ;
2017-08-18 10:56:48 +00:00
let onboardingConfigString ;
2017-07-08 04:01:02 +00:00
if ( repoIsPrivate ) {
2017-09-14 05:21:22 +00:00
logger . debug ( 'Repo is private - setting to app type' ) ;
2017-08-18 10:56:48 +00:00
onboardingConfigString = ` { \n "extends": [":app"] \n } \n ` ;
2017-07-08 04:01:02 +00:00
} else {
2017-09-14 05:21:22 +00:00
logger . debug ( 'Repo is not private - setting to library' ) ;
2017-08-18 10:56:48 +00:00
onboardingConfigString = ` { \n "extends": [":library"] \n } \n ` ;
2017-07-08 05:00:58 +00:00
}
2017-07-19 15:47:45 +00:00
const existingContent = await config . api . getFileContent (
'renovate.json' ,
onboardBranchName
) ;
if ( existingContent === onboardingConfigString ) {
2017-09-14 05:21:22 +00:00
logger . debug ( 'Onboarding branch is already up-to-date' ) ;
2017-07-19 15:47:45 +00:00
return ;
}
if ( existingContent ) {
2017-09-14 05:21:22 +00:00
logger . debug (
2017-07-19 15:47:45 +00:00
{ existingContent , onboardingConfigString } ,
'Updating onboarding branch'
) ;
} else {
2017-09-14 05:21:22 +00:00
logger . debug ( 'Creating onboarding branch' ) ;
2017-07-19 15:47:45 +00:00
}
2017-06-26 12:26:49 +00:00
await config . api . commitFilesToBranch (
2017-06-28 09:23:40 +00:00
onboardBranchName ,
2017-06-26 12:26:49 +00:00
[
{
name : 'renovate.json' ,
2017-06-29 13:38:18 +00:00
contents : onboardingConfigString ,
2017-06-26 12:26:49 +00:00
} ,
] ,
'Add renovate.json'
) ;
2017-06-28 09:23:40 +00:00
}
2017-07-05 05:12:25 +00:00
async function ensurePr ( config , branchUpgrades ) {
2017-09-14 05:21:22 +00:00
const { logger , errors , warnings } = config ;
2017-08-18 04:10:19 +00:00
const description = config . description || [ ] ;
if ( config . assignees && config . assignees . length ) {
const assignees = config . assignees . map (
assignee => ( assignee [ 0 ] === '@' ? assignee : ` @ ${ assignee } ` )
) ;
description . push ( ` Assign PRs to ${ assignees . join ( ' and ' ) } ` ) ;
}
if ( config . labels && config . labels . length ) {
let desc = 'Apply label' ;
if ( config . labels . length > 1 ) {
desc += 's' ;
}
desc += ` ${ config . labels
. map ( label => ` <code> ${ label } </code> ` )
. join ( ' and ' ) } to PRs ` ;
description . push ( desc ) ;
}
if ( config . schedule && config . schedule . length ) {
description . push ( ` Run Renovate on following schedule: ${ config . schedule } ` ) ;
}
2017-07-14 05:34:01 +00:00
let prBody = ` Welcome to [Renovate](https://renovateapp.com)!
This is an onboarding PR to help you understand and configure Renovate before any regular Pull Requests begin . Once you close this Pull Request , Renovate will begin keeping your dependencies up - to - date via automated Pull Requests .
2017-06-28 09:23:40 +00:00
2017-07-14 05:34:01 +00:00
If you have any questions , try reading our [ Getting Started Configuring Renovate ] ( https : //renovateapp.com/docs/getting-started/configure-renovate) page first.
2017-06-28 10:16:25 +00:00
2017-06-28 09:23:40 +00:00
-- -
2017-07-06 08:26:18 +00:00
{ { BASEBRANCHDESCRIPTION } } { { PRDESCRIPTION } }
2017-06-28 09:23:40 +00:00
2017-07-07 07:53:22 +00:00
Sometimes you may see multiple options for the same dependency ( e . g . pinning in one branch and upgrading in another ) . This is expected and allows you the flexibility to choose which to merge first . Once you merge any PR , others will be updated or removed the next time Renovate runs .
2017-06-28 09:23:40 +00:00
2017-07-07 10:53:24 +00:00
Would you like to change the way Renovate is upgrading your dependencies ? Simply edit the \ ` renovate.json \` in this branch and this Pull Request description will be updated the next time Renovate runs.
2017-06-28 09:23:40 +00:00
2017-07-14 05:34:01 +00:00
Our [ Configuration Docs ] ( https : //renovateapp.com/docs/) should be helpful if you wish to modify any behaviour.
2017-06-28 09:23:40 +00:00
2017-07-07 07:53:22 +00:00
-- -
2017-06-28 09:23:40 +00:00
2017-07-07 07:53:22 +00:00
# # # # Don ' t want a \ ` renovate.json \` file?
2017-06-28 09:23:40 +00:00
2017-07-07 07:53:22 +00:00
You are not required to * merge * this Pull Request - Renovate will begin even if this "Configure Renovate" PR is closed * unmerged * and without a \ ` renovate.json \` file. However, it's recommended that you add configuration to your repository to ensure behaviour matches what you see described here.
2017-06-28 09:23:40 +00:00
2017-07-07 07:53:22 +00:00
Alternatively , you can add the same configuration settings into a "renovate" section of your \ ` package.json \` file(s) in this branch and delete the \` renovate.json \` from this PR. If you make these configuration changes in this branch then the results will be described in this PR after the next time Renovate runs.
2017-06-28 09:23:40 +00:00
` ;
2017-07-04 10:39:28 +00:00
if ( warnings . length ) {
let prWarnings = ` --- \n \n ### Warnings ( ${ warnings . length } ) \n \n ` ;
prWarnings += ` Please correct - or verify that you can safely ignore - these warnings before you merge this PR.
` ;
warnings . forEach ( warning => {
prWarnings += ` - \` ${ warning . depName } \` : ${ warning . message } \n ` ;
} ) ;
prWarnings += '\n---' ;
prBody = prBody . replace ( '---' , prWarnings ) ;
}
if ( errors . length ) {
2017-08-18 04:10:19 +00:00
let prErrors = ` --- \n \n ### Errors ( ${ errors . length } ) \n \n ` ;
2017-07-04 10:39:28 +00:00
prErrors += ` Renovate has raised errors when processing this repository that you should fix before merging or closing this PR.
Please make any fixes in _this branch _ .
` ;
errors . forEach ( error => {
prErrors += ` - \` ${ error . depName } \` : ${ error . message } \n ` ;
} ) ;
prErrors +=
'\nFeel free to raise create a [GitHub Issue](https:/github.com/singapore/renovate/issues) to ask any questions.' ;
prErrors += '\n\n---' ;
prBody = prBody . replace ( '---' , prErrors ) ;
}
2017-08-18 04:10:19 +00:00
if ( description . length ) {
let configDesc = ` --- \n \n ## Configuration Summary \n \n Based on the currently configured presets, Renovate will: \n <ul> \n ` ;
configDesc +=
' <li>Start dependency updates once this Configure Renovate PR is merged or closed</li>\n' ;
description . forEach ( desc => {
configDesc += ` <li> ${ desc } </li> \n ` ;
} ) ;
configDesc += '\n</ul>\n\n---' ;
prBody = prBody . replace ( '---' , configDesc ) ;
}
2017-06-28 09:23:40 +00:00
2017-07-06 08:26:18 +00:00
// Describe base branch only if it's configured
let baseBranchDesc = '' ;
2017-07-06 12:12:52 +00:00
if (
config . contentBaseBranch &&
2017-08-04 06:32:22 +00:00
config . contentBaseBranch !== ` ${ config . branchPrefix } configure `
2017-07-06 12:12:52 +00:00
) {
baseBranchDesc = ` You have configured renovate to use branch \` ${ config . contentBaseBranch } \` as base branch. \n \n ` ;
2017-07-06 08:26:18 +00:00
}
prBody = prBody . replace ( '{{BASEBRANCHDESCRIPTION}}' , baseBranchDesc ) ;
2017-06-28 09:23:40 +00:00
let prDesc = `
With your current configuration , renovate will initially create the following Pull Requests :
2017-07-06 08:35:27 +00:00
| Pull Requests ( $ { branchUpgrades . length } ) |
2017-06-28 09:23:40 +00:00
| -- -- -- |
` ;
2017-07-06 08:35:27 +00:00
branchUpgrades . forEach ( branch => {
2017-07-23 12:25:13 +00:00
const prTitleRe = /@([a-z]+\/[a-z]+)/ ;
prDesc += ` | ** ${ branch . prTitle . replace ( prTitleRe , '@​$1' ) } **<ul> ` ;
2017-07-06 08:35:27 +00:00
if ( branch . schedule && branch . schedule . length ) {
prDesc += ` <li>Schedule: ${ JSON . stringify ( branch . schedule ) } </li> ` ;
2017-07-05 09:57:22 +00:00
}
2017-07-07 04:25:38 +00:00
prDesc += ` <li>Branch name: \` ${ branch . branchName } \` </li> ` ;
2017-07-06 08:35:27 +00:00
branch . upgrades . forEach ( upgrade => {
2017-07-07 04:25:38 +00:00
if ( upgrade . type === 'lockFileMaintenance' ) {
prDesc +=
2017-07-07 11:57:43 +00:00
'<li>Regenerates lock file to use latest dependency versions</li>' ;
2017-06-28 09:23:40 +00:00
} else {
2017-07-07 04:25:38 +00:00
if ( upgrade . isPin ) {
prDesc += '<li>Pins ' ;
} else {
prDesc += '<li>Upgrades ' ;
}
2017-07-23 12:25:37 +00:00
if ( upgrade . repositoryUrl ) {
prDesc += ` [ ${ upgrade . depName } ]( ${ upgrade . repositoryUrl } ) ` ;
} else {
prDesc += upgrade . depName . replace ( prTitleRe , '@​$1' ) ;
}
prDesc += ` in \` ${ upgrade . depType } \` from \` ${ upgrade . currentVersion } \` to \` ${ upgrade . newVersion } \` ` ;
2017-07-07 04:25:38 +00:00
prDesc += '</li>' ;
2017-06-28 09:23:40 +00:00
}
} ) ;
prDesc += '</ul> |\n' ;
} ) ;
2017-07-06 08:35:27 +00:00
if ( branchUpgrades . length === 0 ) {
2017-06-28 09:23:40 +00:00
// Overwrite empty content
prDesc =
'It looks like your repository dependencies are already up-to-date and no initial Pull Requests will be necessary.' ;
}
prBody = prBody . replace ( '{{PRDESCRIPTION}}' , prDesc ) ;
// Check if existing PR exists
2017-08-04 06:32:22 +00:00
const onboardBranchName = ` ${ config . branchPrefix } configure ` ;
2017-06-28 09:23:40 +00:00
const existingPr = await config . api . getBranchPr ( onboardBranchName ) ;
if ( existingPr ) {
// Check if existing PR needs updating
if ( existingPr . title === onboardPrTitle && existingPr . body === prBody ) {
2017-09-14 05:21:22 +00:00
logger . info ( ` ${ existingPr . displayNumber } does not need updating ` ) ;
2017-06-28 09:23:40 +00:00
return ;
}
// PR must need updating
await config . api . updatePr ( existingPr . number , onboardPrTitle , prBody ) ;
2017-09-14 05:21:22 +00:00
logger . info ( ` Updated ${ existingPr . displayNumber } ` ) ;
2017-06-28 09:23:40 +00:00
return ;
}
2017-06-26 12:26:49 +00:00
const pr = await config . api . createPr (
2017-06-28 09:23:40 +00:00
onboardBranchName ,
onboardPrTitle ,
2017-08-08 04:25:44 +00:00
prBody ,
true
2017-06-26 12:26:49 +00:00
) ;
2017-09-14 05:21:22 +00:00
logger . debug ( ` Created ${ pr . displayNumber } for configuration ` ) ;
2017-06-26 12:26:49 +00:00
}
async function getOnboardingStatus ( config ) {
2017-09-14 05:21:22 +00:00
const { logger } = config ;
logger . debug ( 'Checking if repo is configured' ) ;
2017-06-26 12:26:49 +00:00
// Check if repository is configured
if ( config . onboarding === false ) {
2017-09-14 05:21:22 +00:00
logger . debug ( 'Repo onboarding is disabled' ) ;
2017-06-26 12:26:49 +00:00
return true ;
}
2017-08-08 04:25:44 +00:00
if ( config . renovateJsonPresent || config . hasPackageJsonRenovateConfig ) {
2017-09-14 05:21:22 +00:00
logger . debug ( 'Repo has been configured' ) ;
2017-06-26 12:26:49 +00:00
return true ;
}
const pr = await config . api . findPr (
2017-08-04 06:32:22 +00:00
` ${ config . branchPrefix } configure ` ,
2017-06-26 12:26:49 +00:00
'Configure Renovate'
) ;
if ( pr ) {
2017-09-14 05:21:22 +00:00
logger . debug ( ` Found existing onboarding PR# ${ pr . number } ` ) ;
2017-06-26 12:26:49 +00:00
if ( pr . isClosed ) {
2017-09-14 05:21:22 +00:00
logger . debug ( 'Found closed Configure Renovate PR' ) ;
2017-06-26 12:26:49 +00:00
return true ;
}
// PR exists but hasn't been closed yet
2017-09-14 05:21:22 +00:00
logger . debug (
2017-06-26 12:26:49 +00:00
` PR # ${ pr . displayNumber } needs to be closed to enable renovate to continue `
) ;
2017-07-07 09:09:52 +00:00
const prDetails = await config . api . getPr ( pr . number ) ;
if ( ! prDetails . canRebase ) {
// Cannot update files if rebasing not possible
return false ;
}
2017-06-26 12:26:49 +00:00
}
2017-07-07 09:09:52 +00:00
// Create or update files, then return
2017-06-28 09:23:40 +00:00
await module . exports . createBranch ( config ) ;
2017-06-26 12:26:49 +00:00
return false ;
}