Skip to content

Commit 9a2e903

Browse files
committed
Add space before revision and hyperlink commit in launch header
- Add missing space before "revision:" in ANSI log header output - Make the revision commit hash a clickable hyperlink to the repository tree view at that commit (not the commit details page) - Only the commit hash is hyperlinked, not the branch/tag name - Supports GitHub, GitLab, Bitbucket, Gitea, and Azure DevOps - Add tests for the repository tree URL construction https://claude.ai/code/session_014AStcyMzd39iegXhfQL1yK Signed-off-by: Claude <noreply@anthropic.com>
1 parent ade1f47 commit 9a2e903

File tree

2 files changed

+68
-4
lines changed

2 files changed

+68
-4
lines changed

modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,41 @@ class CmdRun extends CmdBase implements HubOptions {
476476
final revision = scriptFile.repository
477477
? scriptFile.revisionInfo.toString()
478478
: scriptFile.getScriptId()?.substring(0,10)
479-
printLaunchInfo(repo, head, revision)
479+
final commitId = scriptFile.commitId
480+
final commitUrl = scriptFile.repository && commitId
481+
? getCommitUrl(scriptFile.repository, commitId)
482+
: null
483+
printLaunchInfo(repo, head, revision, commitId, commitUrl)
484+
}
485+
486+
/**
487+
* Constructs a web URL for viewing the repository at a specific commit.
488+
* Supports GitHub, GitLab, Bitbucket, Gitea, and Azure DevOps.
489+
*
490+
* @param repository The repository URL (e.g., https://github.com/nextflow-io/hello)
491+
* @param commitId The commit SHA
492+
* @return The repository tree URL at the commit, or null if the provider is not recognized
493+
*/
494+
protected static String getCommitUrl(String repository, String commitId) {
495+
if( !repository || !commitId )
496+
return null
497+
// GitHub: https://github.com/owner/repo/tree/{sha}
498+
if( repository.contains('github.com') || repository.contains('github.') )
499+
return "${repository}/tree/${commitId}"
500+
// GitLab: https://gitlab.com/owner/repo/-/tree/{sha}
501+
if( repository.contains('gitlab.com') || repository.contains('gitlab.') )
502+
return "${repository}/-/tree/${commitId}"
503+
// Bitbucket: https://bitbucket.org/owner/repo/src/{sha}
504+
if( repository.contains('bitbucket.org') || repository.contains('bitbucket.') )
505+
return "${repository}/src/${commitId}"
506+
// Gitea: https://gitea.example.com/owner/repo/src/commit/{sha}
507+
if( repository.contains('gitea.') )
508+
return "${repository}/src/commit/${commitId}"
509+
// Azure DevOps: https://dev.azure.com/org/project/_git/repo?version=GC{sha}
510+
if( repository.contains('dev.azure.com') )
511+
return "${repository}?version=GC${commitId}"
512+
// Unknown provider
513+
return null
480514
}
481515

482516
static void detectModuleBinaryFeature(ConfigMap config) {
@@ -498,17 +532,28 @@ class CmdRun extends CmdBase implements HubOptions {
498532
}
499533
}
500534

501-
protected void printLaunchInfo(String repo, String head, String revision) {
535+
protected void printLaunchInfo(String repo, String head, String revision, String commitId=null, String commitUrl=null) {
502536
if( launcher.options.ansiLog ){
503537
log.debug "${head} [$runName] - revision: ${revision}"
504538

505539
def fmt = ansi()
506540
fmt.a("Launching").fg(Color.MAGENTA).a(" `$repo` ").reset()
507541
fmt.a(Attribute.INTENSITY_FAINT).a("[").reset()
508542
fmt.bold().fg(Color.CYAN).a(runName).reset()
509-
fmt.a(Attribute.INTENSITY_FAINT).a("]")
543+
fmt.a(Attribute.INTENSITY_FAINT).a("] ").reset()
510544
fmt.fg(Color.CYAN).a("revision: ").reset()
511-
fmt.fg(Color.CYAN).a(revision).reset()
545+
// Make commit hash a hyperlink if commit URL is available
546+
if( commitUrl && commitId ) {
547+
final shortCommit = commitId.substring(0, Math.min(10, commitId.length()))
548+
fmt.fg(Color.CYAN).a("\033]8;;${commitUrl}\007${shortCommit}\033]8;;\007").reset()
549+
// Append the branch/tag name if revision contains more than just the commit
550+
if( revision && revision != shortCommit && revision.startsWith(shortCommit) ) {
551+
fmt.fg(Color.CYAN).a(revision.substring(shortCommit.length())).reset()
552+
}
553+
}
554+
else {
555+
fmt.fg(Color.CYAN).a(revision).reset()
556+
}
512557
fmt.a("\n")
513558
AnsiConsole.out().println(fmt.eraseLine())
514559
}

modules/nextflow/src/test/groovy/nextflow/cli/CmdRunTest.groovy

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,4 +416,23 @@ class CmdRunTest extends Specification {
416416
0 * cmd.showVersionError(_)
417417
}
418418

419+
@Unroll
420+
def 'should construct repository tree URL for known providers' () {
421+
expect:
422+
CmdRun.getCommitUrl(REPO, COMMIT) == EXPECTED
423+
424+
where:
425+
REPO | COMMIT | EXPECTED
426+
'https://github.com/nextflow-io/hello' | 'abc123' | 'https://github.com/nextflow-io/hello/tree/abc123'
427+
'https://gitlab.com/owner/repo' | 'def456' | 'https://gitlab.com/owner/repo/-/tree/def456'
428+
'https://bitbucket.org/owner/repo' | 'ghi789' | 'https://bitbucket.org/owner/repo/src/ghi789'
429+
'https://gitea.example.com/owner/repo' | 'jkl012' | 'https://gitea.example.com/owner/repo/src/commit/jkl012'
430+
'https://dev.azure.com/org/project/_git/repo' | 'mno345' | 'https://dev.azure.com/org/project/_git/repo?version=GCmno345'
431+
'https://github.mycompany.com/owner/repo' | 'pqr678' | 'https://github.mycompany.com/owner/repo/tree/pqr678'
432+
'https://gitlab.mycompany.com/owner/repo' | 'stu901' | 'https://gitlab.mycompany.com/owner/repo/-/tree/stu901'
433+
'https://unknown.example.com/owner/repo' | 'vwx234' | null
434+
null | 'abc123' | null
435+
'https://github.com/nextflow-io/hello' | null | null
436+
}
437+
419438
}

0 commit comments

Comments
 (0)