Skip to content

Commit

Permalink
Merge pull request #54 from nf-core/tower-actions-testing
Browse files Browse the repository at this point in the history
Tower actions testing
  • Loading branch information
robsyme authored Mar 30, 2023
2 parents 2ccd646 + 0a56d1e commit d671974
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 3 deletions.
95 changes: 95 additions & 0 deletions .github/workflows/cloud_tests_full.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: full-sized tests on cloud providers
run-name: Submitting workflow to all cloud providers using full sized data
on:
release:
types: [published]
inputs:
platform:
description: "Platform to run test"
default: "all"
workflow_dispatch:
inputs:
platform:
description: "Platform to run test"
required: true
default: "all"
type: choice
options:
- all
- aws
- azure
- gcp
jobs:
run-full-tests-on-aws:
if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'aws' }}
runs-on: ubuntu-latest
strategy:
matrix:
aligner: ["star_salmon", "star_rsem"]
steps:
- uses: seqeralabs/action-tower-launch@v1
with:
workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }}
access_token: ${{ secrets.TOWER_ACCESS_TOKEN }}
compute_env: ${{ secrets.TOWER_CE_AWS_CPU }}
workdir: "${{ secrets.TOWER_BUCKET_AWS }}/work/testpipeline/work-${{ github.sha }}"
run_name: "aws_testpipeline_${{ matrix.aligner }}"
profiles: test
parameters: |
{
"hook_url": "${{ secrets.MEGATESTS_ALERTS_SLACK_HOOK_URL }}",
"outdir": "${{ secrets.TOWER_BUCKET_AWS }}/rnaseq/results-${{ github.sha }}/aligner_${{ matrix.aligner }}"
}
- uses: actions/upload-artifact@v3
with:
name: Tower debug log file
path: tower_action_*.log
run-full-tests-on-gcp:
if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'gcp' }}
runs-on: ubuntu-latest
strategy:
matrix:
aligner: ["star_salmon", "star_rsem"]
steps:
- uses: seqeralabs/action-tower-launch@v1
with:
workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }}
access_token: ${{ secrets.TOWER_ACCESS_TOKEN }}
compute_env: ${{ secrets.TOWER_CE_GCP_CPU }}
workdir: "${{ secrets.TOWER_BUCKET_GCP }}/work/testpipeline/work-${{ github.sha }}"
run_name: "gcp_testpipeline_${{ matrix.aligner }}"
profiles: test
parameters: |
{
"hook_url": "${{ secrets.MEGATESTS_ALERTS_SLACK_HOOK_URL }}",
"outdir": "${{ secrets.TOWER_BUCKET_GCP }}/rnaseq/results-${{ github.sha }}/aligner_${{ matrix.aligner }}"
}
- uses: actions/upload-artifact@v3
with:
name: Tower debug log file
path: tower_action_*.log
run-full-tests-on-azure:
if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'azure' }}
runs-on: ubuntu-latest
strategy:
matrix:
aligner: ["star_salmon", "star_rsem"]
steps:
- uses: seqeralabs/action-tower-launch@v1
with:
workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }}
access_token: ${{ secrets.TOWER_ACCESS_TOKEN }}
compute_env: ${{ secrets.TOWER_CE_AZURE_CPU }}
workdir: "${{ secrets.TOWER_BUCKET_AZURE }}/work/testpipeline/work-${{ github.sha }}"
run_name: "azure_testpipeline_${{ matrix.aligner }}"
profiles: test
parameters: |
{
"hook_url": "${{ secrets.MEGATESTS_ALERTS_SLACK_HOOK_URL }}",
"outdir": "${{ secrets.TOWER_BUCKET_AZURE }}/rnaseq/results-${{ github.sha }}/aligner_${{ matrix.aligner }}",
"igenomes_base": "${{ secrets.TOWER_IGENOMES_BASE_AZURE }}"
}
- uses: actions/upload-artifact@v3
with:
name: Tower debug log file
path: tower_action_*.log
34 changes: 34 additions & 0 deletions assets/slackreport.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"attachments": [
{
"fallback": "Plain-text summary of the attachment.",
"color": "<% if (success) { %>good<% } else { %>danger<%} %>",
"author_name": "sanger-tol/readmapping v${version} - ${runName}",
"author_icon": "https://www.nextflow.io/docs/latest/_static/favicon.ico",
"text": "<% if (success) { %>Pipeline completed successfully!<% } else { %>Pipeline completed with errors<% } %>",
"fields": [
{
"title": "Command used to launch the workflow",
"value": "```${commandLine}```",
"short": false
}
<%
if (!success) { %>
,
{
"title": "Full error message",
"value": "```${errorReport}```",
"short": false
},
{
"title": "Pipeline configuration",
"value": "<% out << summary.collect{ k,v -> k == "hook_url" ? "_${k}_: (_hidden_)" : ( ( v.class.toString().contains('Path') || ( v.class.toString().contains('String') && v.contains('/') ) ) ? "_${k}_: `${v}`" : (v.class.toString().contains('DateTime') ? ("_${k}_: " + v.format(java.time.format.DateTimeFormatter.ofLocalizedDateTime(java.time.format.FormatStyle.MEDIUM))) : "_${k}_: ${v}") ) }.join(",\n") %>",
"short": false
}
<% }
%>
],
"footer": "Completed at <% out << dateComplete.format(java.time.format.DateTimeFormatter.ofLocalizedDateTime(java.time.format.FormatStyle.MEDIUM)) %> (duration: ${duration})"
}
]
}
84 changes: 81 additions & 3 deletions lib/NfcoreTemplate.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,25 @@ class NfcoreTemplate {
}
}

//
// Generate version string
//
public static String version(workflow) {
String version_string = ""

if (workflow.manifest.version) {
def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : ''
version_string += "${prefix_v}${workflow.manifest.version}"
}

if (workflow.commitId) {
def git_shortsha = workflow.commitId.substring(0, 7)
version_string += "-g${git_shortsha}"
}

return version_string
}

//
// Construct and send completion email
//
Expand Down Expand Up @@ -61,7 +80,7 @@ class NfcoreTemplate {
misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp

def email_fields = [:]
email_fields['version'] = workflow.manifest.version
email_fields['version'] = NfcoreTemplate.version(workflow)
email_fields['runName'] = workflow.runName
email_fields['success'] = workflow.success
email_fields['dateComplete'] = workflow.complete
Expand Down Expand Up @@ -145,6 +164,64 @@ class NfcoreTemplate {
output_tf.withWriter { w -> w << email_txt }
}

//
// Construct and send a notification to a web server as JSON
// e.g. Microsoft Teams and Slack
//
public static void IM_notification(workflow, params, summary_params, projectDir, log) {
def hook_url = params.hook_url

def summary = [:]
for (group in summary_params.keySet()) {
summary << summary_params[group]
}

def misc_fields = [:]
misc_fields['start'] = workflow.start
misc_fields['complete'] = workflow.complete
misc_fields['scriptfile'] = workflow.scriptFile
misc_fields['scriptid'] = workflow.scriptId
if (workflow.repository) misc_fields['repository'] = workflow.repository
if (workflow.commitId) misc_fields['commitid'] = workflow.commitId
if (workflow.revision) misc_fields['revision'] = workflow.revision
misc_fields['nxf_version'] = workflow.nextflow.version
misc_fields['nxf_build'] = workflow.nextflow.build
misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp

def msg_fields = [:]
msg_fields['version'] = NfcoreTemplate.version(workflow)
msg_fields['runName'] = workflow.runName
msg_fields['success'] = workflow.success
msg_fields['dateComplete'] = workflow.complete
msg_fields['duration'] = workflow.duration
msg_fields['exitStatus'] = workflow.exitStatus
msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None')
msg_fields['errorReport'] = (workflow.errorReport ?: 'None')
msg_fields['commandLine'] = workflow.commandLine.replaceFirst(/ +--hook_url +[^ ]+/, "")
msg_fields['projectDir'] = workflow.projectDir
msg_fields['summary'] = summary << misc_fields

// Render the JSON template
def engine = new groovy.text.GStringTemplateEngine()
// Different JSON depending on the service provider
// Defaults to "Adaptive Cards" (https://adaptivecards.io), except Slack which has its own format
def json_path = hook_url.contains("hooks.slack.com") ? "slackreport.json" : "adaptivecard.json"
def hf = new File("$projectDir/assets/${json_path}")
def json_template = engine.createTemplate(hf).make(msg_fields)
def json_message = json_template.toString()

// POST
def post = new URL(hook_url).openConnection();
post.setRequestMethod("POST")
post.setDoOutput(true)
post.setRequestProperty("Content-Type", "application/json")
post.getOutputStream().write(json_message.getBytes("UTF-8"));
def postRC = post.getResponseCode();
if (! postRC.equals(200)) {
log.warn(post.getErrorStream().getText());
}
}

//
// Print pipeline summary on completion
//
Expand All @@ -154,7 +231,7 @@ class NfcoreTemplate {
if (workflow.stats.ignoredCount == 0) {
log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-"
} else {
log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed successfully, but with errored process(es) ${colors.reset}-"
log.info "-${colors.purple}[$workflow.manifest.name]${colors.yellow} Pipeline completed successfully, but with errored process(es) ${colors.reset}-"
}
} else {
log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-"
Expand Down Expand Up @@ -242,6 +319,7 @@ class NfcoreTemplate {
//
public static String logo(workflow, monochrome_logs) {
Map colors = logColours(monochrome_logs)
String workflow_version = NfcoreTemplate.version(workflow)
String.format(
"""\n
${dashedLine(monochrome_logs)}
Expand All @@ -250,7 +328,7 @@ class NfcoreTemplate {
${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset}
${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset}
${colors.green}`._,._,\'${colors.reset}
${colors.purple} ${workflow.manifest.name} v${workflow.manifest.version}${colors.reset}
${colors.purple} ${workflow.manifest.name} ${workflow_version}${colors.reset}
${dashedLine(monochrome_logs)}
""".stripIndent()
)
Expand Down
1 change: 1 addition & 0 deletions nextflow.config
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ params {
email_on_fail = null
plaintext_email = false
monochrome_logs = false
hook_url = null
help = false
validate_params = true
show_hidden_params = false
Expand Down
7 changes: 7 additions & 0 deletions nextflow_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,13 @@
"fa_icon": "fas fa-palette",
"hidden": true
},
"hook_url": {
"type": "string",
"description": "Incoming hook URL for messaging service",
"fa_icon": "fas fa-people-group",
"help_text": "Incoming hook URL for messaging service. Currently, MS Teams and Slack are supported.",
"hidden": true
},
"multiqc_config": {
"type": "string",
"description": "Custom config file to supply to MultiQC.",
Expand Down
3 changes: 3 additions & 0 deletions workflows/testpipeline.nf
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ workflow.onComplete {
NfcoreTemplate.email(workflow, params, summary_params, projectDir, log, multiqc_report)
}
NfcoreTemplate.summary(workflow, params, log)
if (params.hook_url) {
NfcoreTemplate.IM_notification(workflow, params, summary_params, projectDir, log)
}
}

/*
Expand Down

0 comments on commit d671974

Please sign in to comment.