2023-02-21 21:07:11 -05:00
import { danger , warn , message , results } from "danger"
2023-02-07 04:46:03 -05:00
/ * *
* Check if MR Title contains prefix "Draft: ... or " WIP : ... " .
*
* @ dangerjs WARN
* /
function checkMrTitle ( ) {
const mrTitle = danger . gitlab . mr . title
2023-02-28 02:15:21 -05:00
const regexWip = /^WIP:/i ;
const regexDraft = /^DRAFT:/i ;
if ( ( regexWip . test ( mrTitle ) ) || ( regexDraft . test ( mrTitle ) ) ) {
return warn ( "Please remove the `WIP:`/`DRAFT:` prefix from the MR name before merging this MR." ) ;
2023-02-07 04:46:03 -05:00
}
}
checkMrTitle ( ) ;
/ * *
* Check if MR Description is longer than 50 characters " .
*
* @ dangerjs WARN
* /
function checkMrDescription ( ) {
const shortMrDescriptionThreshold = 50 ; // MR description is considered too short below this number of characters
const mrDescription = danger . gitlab . mr . description
if ( mrDescription . length < shortMrDescriptionThreshold ) {
return warn ( "The MR description looks very brief, please check if more details can be added." ) ;
}
}
checkMrDescription ( ) ;
/ * *
* Check if MR Description contains mandatory section "Release notes"
*
* # TODO : this simple logic will be improved in future MRs - Jira IDF - 6852
*
* @ dangerjs WARN
* /
function checkMrReleaseNotes ( ) {
const mrDescription = danger . gitlab . mr . description
if ( ! mrDescription . toUpperCase ( ) . includes ( "## Release notes" . toUpperCase ( ) ) ) {
return warn ( "Please update the MR description, the mandatory section `Release Notes` seems to be missing." ) ;
}
}
checkMrReleaseNotes ( ) ;
/ * *
* Check if MR Description contains JIRA issues references
*
* Check if the associated GitHub Jira ticket has a GitHub closure reference in the commit message .
*
* # TODO : this simple logic will be improved in future MRs - Jira IDF - 6854
*
* @ dangerjs WARN
* /
function checkMrJiraLinks ( ) {
const mrDescription = danger . gitlab . mr . description
const mrCommitMessages = danger . gitlab . commits . map ( commit => commit . message ) ;
const matchBlockRelated = mrDescription . match ( / \ # \ # R e l a t e d . * $ / s ) ; / / M a t c h M R d e s c r i p t i o n s t a r t i n g w i t h l i n e # # R e l a t e d t i l l t h e e n d o f M R d e s c r i p t i o n
2023-02-21 21:07:35 -05:00
const noRelatedIssues = /No related issues/ . test ( matchBlockRelated ? matchBlockRelated [ 0 ] : '' ) ; // Check if there is "No related issues"
2023-02-07 04:46:03 -05:00
const testJiraLabels = /[A-Z]+-[0-9]+/ . test ( matchBlockRelated ? matchBlockRelated [ 0 ] : '' ) ; // Test if pattern of Jira label "JIRA-1234" or "RDT-311" is in section Related
const ghIssueTicket = /IDFGH-[0-9]+/ . test ( matchBlockRelated ? matchBlockRelated [ 0 ] : '' ) ; // Check if there is JIRA link starts with "IDFGH-*" in MR description, section "Related"
2023-02-20 21:18:07 -05:00
const testGithubLink = /Closes https:\/\/github\.com\/espressif\/esp-idf\/issues\/[0-9]+/
2023-02-07 04:46:03 -05:00
2023-02-21 21:07:35 -05:00
if ( mrDescription . toUpperCase ( ) . includes ( "## RELATED" ) && noRelatedIssues ) {
return
}
2023-02-07 04:46:03 -05:00
if ( ! mrDescription . toUpperCase ( ) . includes ( "## RELATED" ) || ! testJiraLabels ) { // Missing section "Related" or missing links to JIRA tickets
2023-02-28 03:42:07 -05:00
return message ( "Please consider adding references to JIRA issues in the `Related` section of the MR description." ) ;
2023-02-07 04:46:03 -05:00
} else if ( ghIssueTicket ) { // Found JIRA ticket linked GitHub issue
2023-02-20 21:18:07 -05:00
if ( ! testGithubLink . test ( mrCommitMessages ) ) { // Commit message does not contain a link to close the issue on GitHub
2023-02-07 04:46:03 -05:00
return warn ( "Please add GitHub issue closing link `Closes https://github.com/espressif/esp-idf/issues/<github-issue-number>` to the commit message." ) ;
}
}
}
checkMrJiraLinks ( ) ;
/ * *
* Check if MR has not an excessive numbers of commits ( if squashed )
*
* # TODO : this simple logic will be improved in future MRs - Jira IDF - 6856.
*
* @ dangerjs INFO
* /
function checkMrTooManyCommits ( ) {
const tooManyCommitThreshold = 5 // above this number of commits, squash is recommended
const mrCommits = danger . gitlab . commits
if ( mrCommits . length > tooManyCommitThreshold ) {
return message ( ` You might consider squashing your ${ mrCommits . length } commits (simplifying branch history). ` ) ;
}
}
checkMrTooManyCommits ( ) ;
/ * *
* Check commit message are descriptive enough ( longer that 10 characters )
* @ dangerjs WARN
* /
function checkMrCommitMessagesLength ( ) {
const shortCommitMessageThreshold = 10 ; // commit message is considered too short below this number of characters
const mrCommit = danger . gitlab . commits
let shortCommitMessages = [ ] ;
for ( let i = 0 ; i < mrCommit . length ; i ++ ) {
const commitMessage = mrCommit [ i ] . message ;
if ( commitMessage . length < shortCommitMessageThreshold ) {
shortCommitMessages . push ( ` - commit message: ${ commitMessage } ` ) ;
}
}
if ( shortCommitMessages . length ) {
warn ( ` Some of your commit messages may not be sufficiently descriptive (are shorter than ${ shortCommitMessageThreshold } characters):
\ n$ { shortCommitMessages . join ( "" ) }
\ nYou might consider squashing commits ( simplifying branch history ) or updating those short commit messages . ` );
}
}
checkMrCommitMessagesLength ( ) ;
/ * *
* Check if MR is too large ( more than 1000 lines of changes )
*
* @ dangerjs INFO
* /
function checkMrIsTooLarge ( ) {
const bigMrLinesOfCodeThreshold = 1000
danger . git . linesOfCode ( )
. then ( ( totalLines ) => {
if ( totalLines > bigMrLinesOfCodeThreshold ) {
return message ( ` This MR seems to be quiet large (total lines of code: ${ totalLines } ), you might consider splitting it into smaller MRs ` ) ;
}
} ) ;
}
checkMrIsTooLarge ( ) ;
/ * *
* Check if documentation needs translation labels
*
* # TODO : this simple logic will be improved in future MRs - Jira IDF - 6855.
*
* @ dangerjs WARN
* /
function checkMrNeedsTranlation ( ) {
const mrLabels = danger . gitlab . mr . labels
const changesInDocsEN = /docs\/en/ . test ( danger . git . modified _files ? danger . git . modified _files [ 0 ] : '' ) ; // Test if changes in directory "docs/EN"
const changesInDocsCH = /docs\/zh_CN/ . test ( danger . git . modified _files ? danger . git . modified _files [ 0 ] : '' ) ; // Test if changes in directory "docs/CH"
// Only English docs has been changed
if ( changesInDocsEN && ! changesInDocsCH ) {
if ( ! mrLabels . includes ( "needs translation: CN" ) ) {
return warn ( "The updated documentation will need to be translated into Chinese, please add the MR label `needs translation: CN`" ) ;
}
}
// Only Chineese docs has been changed
if ( ! changesInDocsEN && changesInDocsCH ) {
if ( ! mrLabels . includes ( "needs translation: EN" ) ) {
return warn ( "The updated documentation will need to be translated into English, please add the MR label `needs translation: EN`" ) ;
}
}
}
checkMrNeedsTranlation ( ) ;
/ * *
* Add a link to manual retry a DangerJS job ( without committing to the repository )
*
* @ dangerjs MARKDOWN
* /
function addRetryLink ( ) {
const retryLink = ` ${ process . env . DANGER _GITLAB _HOST } / ${ process . env . CI _PROJECT _PATH } /-/jobs/ ${ process . env . CI _JOB _ID } `
return markdown ( ` *** \n #### :repeat: If you want to run these checks again, please retry this [DangerJS job]( ${ retryLink } ) \n *** ` ) ;
}
addRetryLink ( ) ;
2023-02-21 21:07:11 -05:00
function printSuccessLog ( ) {
if ( results . fails . length === 0 && results . warnings . length === 0 && results . messages . length === 0 ) {
return message ( 'Good Job! All checks are passing!' )
}
}
printSuccessLog ( ) ;