Skip to content

Commit 178f2c6

Browse files
ewelsclaude
andauthored
Add Nextflow lint GitHub Actions workflow (#739)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent e4a63d6 commit 178f2c6

File tree

3 files changed

+166
-0
lines changed

3 files changed

+166
-0
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Nextflow Lint Comment
2+
3+
on:
4+
workflow_run:
5+
workflows: ["Nextflow Lint"]
6+
types:
7+
- completed
8+
9+
permissions:
10+
contents: read
11+
pull-requests: write
12+
13+
jobs:
14+
comment:
15+
if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request'
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Download lint results
19+
uses: actions/download-artifact@v4
20+
with:
21+
name: lint-results
22+
github-token: ${{ github.token }}
23+
run-id: ${{ github.event.workflow_run.id }}
24+
25+
- name: Get PR info and report
26+
id: pr-info
27+
run: |
28+
PR_NUMBER=$(cat pr-number.txt)
29+
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
30+
echo "comment<<EOF" >> $GITHUB_OUTPUT
31+
cat report.md >> $GITHUB_OUTPUT
32+
echo "EOF" >> $GITHUB_OUTPUT
33+
34+
- name: Find existing comment
35+
uses: peter-evans/find-comment@v3
36+
id: find-comment
37+
with:
38+
issue-number: ${{ steps.pr-info.outputs.pr_number }}
39+
comment-author: "github-actions[bot]"
40+
body-includes: "Nextflow Lint Results"
41+
42+
- name: Create or update PR comment
43+
uses: peter-evans/create-or-update-comment@v4
44+
with:
45+
comment-id: ${{ steps.find-comment.outputs.comment-id }}
46+
issue-number: ${{ steps.pr-info.outputs.pr_number }}
47+
body: ${{ steps.pr-info.outputs.comment }}
48+
edit-mode: replace
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
name: Nextflow Lint
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
lint:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
13+
- name: Install Nextflow
14+
uses: nf-core/setup-nextflow@v2
15+
16+
- name: Run Nextflow lint
17+
run: |
18+
mkdir -p lint-results
19+
# TODO: Remove '|| true' to fail CI when linting errors are fixed
20+
nextflow lint **/solutions/* -o json > lint-results/lint-output.json 2>&1 || true
21+
22+
- name: Generate markdown report
23+
if: always()
24+
uses: actions/github-script@v7
25+
with:
26+
script: |
27+
const fs = require('fs');
28+
const lintOutput = JSON.parse(fs.readFileSync('lint-results/lint-output.json', 'utf8'));
29+
const { summary, errors, warnings } = lintOutput;
30+
const sha = context.sha;
31+
const repo = `${context.repo.owner}/${context.repo.repo}`;
32+
33+
// Handle warnings array (added in future Nextflow version)
34+
const warningsArray = warnings || [];
35+
const warningCount = summary.warnings || 0;
36+
37+
let markdown = '**Nextflow linting complete!**\n\n';
38+
39+
const hasIssues = summary.errors > 0 || warningCount > 0;
40+
41+
if (!hasIssues) {
42+
markdown += `✅ ${summary.filesWithoutErrors} files had no errors\n`;
43+
} else {
44+
if (summary.errors > 0) {
45+
markdown += `❌ ${summary.filesWithErrors} files had ${summary.errors} errors\n`;
46+
}
47+
if (warningCount > 0) {
48+
const filesWithWarnings = summary.filesWithWarnings || 'N/A';
49+
markdown += `⚠️ ${filesWithWarnings} files had ${warningCount} warnings\n`;
50+
}
51+
markdown += `✅ ${summary.filesWithoutErrors} files had no errors\n\n`;
52+
53+
// Combine errors and warnings with type labels
54+
const allIssues = [
55+
...errors.map(e => ({ ...e, type: 'Error' })),
56+
...warningsArray.map(w => ({ ...w, type: 'Warning' }))
57+
];
58+
59+
// Group by file
60+
const grouped = {};
61+
for (const issue of allIssues) {
62+
if (!grouped[issue.filename]) {
63+
grouped[issue.filename] = [];
64+
}
65+
grouped[issue.filename].push(issue);
66+
}
67+
68+
// Build table rows
69+
const rows = [];
70+
for (const [filename, fileIssues] of Object.entries(grouped).sort()) {
71+
for (const issue of fileIssues) {
72+
const location = `${issue.startLine}:${issue.startColumn}`;
73+
const link = `[${filename}:${location}](https://github.com/${repo}/blob/${sha}/${filename}#L${issue.startLine})`;
74+
rows.push(`| ${issue.type} | ${link} | ${issue.message} |`);
75+
}
76+
}
77+
78+
const totalIssues = summary.errors + warningCount;
79+
markdown += `<sup>💡 Tip: Click filename locations to go directly to that code.</sup>\n\n`;
80+
markdown += `<details>\n<summary>View all ${totalIssues} issues</summary>\n\n`;
81+
markdown += `| Type | Location | Message |\n|------|----------|---------|\n`;
82+
markdown += rows.join('\n');
83+
markdown += `\n\n</details>\n`;
84+
}
85+
86+
// Write to file
87+
fs.writeFileSync('lint-results/report.md', markdown);
88+
89+
// Add to job summary
90+
await core.summary
91+
.addRaw(markdown)
92+
.write();
93+
94+
- name: Save PR info
95+
if: always() && github.event_name == 'pull_request'
96+
run: |
97+
echo "${{ github.event.pull_request.number }}" > lint-results/pr-number.txt
98+
echo "${{ github.sha }}" > lint-results/head-sha.txt
99+
100+
- name: Upload lint results
101+
if: always() && github.event_name == 'pull_request'
102+
uses: actions/upload-artifact@v4
103+
with:
104+
name: lint-results
105+
path: lint-results/
106+
retention-days: 1

CONTRIBUTING.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Table of contents:
1111
- [Figures \& diagrams](#figures--diagrams)
1212
- [Content style and formatting](#content-style-and-formatting)
1313
- [Formatting / linting](#formatting--linting)
14+
- [Nextflow linting](#nextflow-linting)
1415
- [Headings CI tests](#headings-ci-tests)
1516
- [Admonitions](#admonitions)
1617
- [Known limitations](#known-limitations)
@@ -137,6 +138,17 @@ Doing that produces cleaner diffs for future code reviews.
137138
The sentences will still be rendered as a continuous paragraph.
138139
For an example, have a look at the code for this paragraph.
139140

141+
### Nextflow linting
142+
143+
This repository uses `nextflow lint` to check Nextflow scripts for errors and warnings.
144+
The linter runs automatically in CI and posts results as a PR comment.
145+
146+
To run locally:
147+
148+
```bash
149+
nextflow lint .
150+
```
151+
140152
### Headings CI tests
141153

142154
This repository includes a Python tool to validate markdown heading numbering consistency across training materials.

0 commit comments

Comments
 (0)