|
| 1 | +/* |
| 2 | + * Functions to be run on completion of pipeline |
| 3 | + */ |
| 4 | + |
| 5 | +class Completion { |
| 6 | + static void email(workflow, params, summary_params, projectDir, log, multiqc_report=[]) { |
| 7 | + |
| 8 | + // Set up the e-mail variables |
| 9 | + def subject = "[$workflow.manifest.name] Successful: $workflow.runName" |
| 10 | + |
| 11 | + if (!workflow.success) { |
| 12 | + subject = "[$workflow.manifest.name] FAILED: $workflow.runName" |
| 13 | + } |
| 14 | + |
| 15 | + def summary = [:] |
| 16 | + for (group in summary_params.keySet()) { |
| 17 | + summary << summary_params[group] |
| 18 | + } |
| 19 | + |
| 20 | + def misc_fields = [:] |
| 21 | + misc_fields['Date Started'] = workflow.start |
| 22 | + misc_fields['Date Completed'] = workflow.complete |
| 23 | + misc_fields['Pipeline script file path'] = workflow.scriptFile |
| 24 | + misc_fields['Pipeline script hash ID'] = workflow.scriptId |
| 25 | + if (workflow.repository) misc_fields['Pipeline repository Git URL'] = workflow.repository |
| 26 | + if (workflow.commitId) misc_fields['Pipeline repository Git Commit'] = workflow.commitId |
| 27 | + if (workflow.revision) misc_fields['Pipeline Git branch/tag'] = workflow.revision |
| 28 | + misc_fields['Nextflow Version'] = workflow.nextflow.version |
| 29 | + misc_fields['Nextflow Build'] = workflow.nextflow.build |
| 30 | + misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp |
| 31 | + |
| 32 | + def email_fields = [:] |
| 33 | + email_fields['version'] = workflow.manifest.version |
| 34 | + email_fields['runName'] = workflow.runName |
| 35 | + email_fields['success'] = workflow.success |
| 36 | + email_fields['dateComplete'] = workflow.complete |
| 37 | + email_fields['duration'] = workflow.duration |
| 38 | + email_fields['exitStatus'] = workflow.exitStatus |
| 39 | + email_fields['errorMessage'] = (workflow.errorMessage ?: 'None') |
| 40 | + email_fields['errorReport'] = (workflow.errorReport ?: 'None') |
| 41 | + email_fields['commandLine'] = workflow.commandLine |
| 42 | + email_fields['projectDir'] = workflow.projectDir |
| 43 | + email_fields['summary'] = summary << misc_fields |
| 44 | + |
| 45 | + // On success try attach the multiqc report |
| 46 | + def mqc_report = null |
| 47 | + try { |
| 48 | + if (workflow.success) { |
| 49 | + mqc_report = multiqc_report.getVal() |
| 50 | + if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { |
| 51 | + if (mqc_report.size() > 1) { |
| 52 | + log.warn "[$workflow.manifest.name] Found multiple reports from process 'MULTIQC', will use only one" |
| 53 | + } |
| 54 | + mqc_report = mqc_report[0] |
| 55 | + } |
| 56 | + } |
| 57 | + } catch (all) { |
| 58 | + log.warn "[$workflow.manifest.name] Could not attach MultiQC report to summary email" |
| 59 | + } |
| 60 | + |
| 61 | + // Check if we are only sending emails on failure |
| 62 | + def email_address = params.email |
| 63 | + if (!params.email && params.email_on_fail && !workflow.success) { |
| 64 | + email_address = params.email_on_fail |
| 65 | + } |
| 66 | + |
| 67 | + // Render the TXT template |
| 68 | + def engine = new groovy.text.GStringTemplateEngine() |
| 69 | + def tf = new File("$projectDir/assets/email_template.txt") |
| 70 | + def txt_template = engine.createTemplate(tf).make(email_fields) |
| 71 | + def email_txt = txt_template.toString() |
| 72 | + |
| 73 | + // Render the HTML template |
| 74 | + def hf = new File("$projectDir/assets/email_template.html") |
| 75 | + def html_template = engine.createTemplate(hf).make(email_fields) |
| 76 | + def email_html = html_template.toString() |
| 77 | + |
| 78 | + // Render the sendmail template |
| 79 | + def max_multiqc_email_size = params.max_multiqc_email_size as nextflow.util.MemoryUnit |
| 80 | + def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "$projectDir", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes()] |
| 81 | + def sf = new File("$projectDir/assets/sendmail_template.txt") |
| 82 | + def sendmail_template = engine.createTemplate(sf).make(smail_fields) |
| 83 | + def sendmail_html = sendmail_template.toString() |
| 84 | + |
| 85 | + // Send the HTML e-mail |
| 86 | + Map colors = Headers.log_colours(params.monochrome_logs) |
| 87 | + if (email_address) { |
| 88 | + try { |
| 89 | + if (params.plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } |
| 90 | + // Try to send HTML e-mail using sendmail |
| 91 | + [ 'sendmail', '-t' ].execute() << sendmail_html |
| 92 | + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (sendmail)-" |
| 93 | + } catch (all) { |
| 94 | + // Catch failures and try with plaintext |
| 95 | + def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] |
| 96 | + if ( mqc_report.size() <= max_multiqc_email_size.toBytes() ) { |
| 97 | + mail_cmd += [ '-A', mqc_report ] |
| 98 | + } |
| 99 | + mail_cmd.execute() << email_html |
| 100 | + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (mail)-" |
| 101 | + } |
| 102 | + } |
| 103 | + |
| 104 | + // Write summary e-mail HTML to a file |
| 105 | + def output_d = new File("${params.outdir}/pipeline_info/") |
| 106 | + if (!output_d.exists()) { |
| 107 | + output_d.mkdirs() |
| 108 | + } |
| 109 | + def output_hf = new File(output_d, "pipeline_report.html") |
| 110 | + output_hf.withWriter { w -> w << email_html } |
| 111 | + def output_tf = new File(output_d, "pipeline_report.txt") |
| 112 | + output_tf.withWriter { w -> w << email_txt } |
| 113 | + } |
| 114 | + |
| 115 | + static void summary(workflow, params, log, fail_percent_mapped=[:], pass_percent_mapped=[:]) { |
| 116 | + Map colors = Headers.log_colours(params.monochrome_logs) |
| 117 | + |
| 118 | + if (workflow.success) { |
| 119 | + if (workflow.stats.ignoredCount == 0) { |
| 120 | + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" |
| 121 | + } else { |
| 122 | + log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" |
| 123 | + } |
| 124 | + } else { |
| 125 | + Checks.hostname(workflow, params, log) |
| 126 | + log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" |
| 127 | + } |
| 128 | + } |
| 129 | +} |
0 commit comments