Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions modules/nextflow/src/main/groovy/nextflow/cli/CmdPush.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright 2013-2024, Seqera Labs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package nextflow.cli
import com.beust.jcommander.Parameter
import com.beust.jcommander.Parameters
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import nextflow.exception.AbortOperationException
import nextflow.plugin.Plugins
import nextflow.scm.AssetManager
import nextflow.scm.PushManager
import nextflow.util.TestOnly
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.transport.RemoteConfig
import org.eclipse.jgit.transport.URIish


/**
* CLI sub-command Push
*
* @author Jorge Ejarque <[email protected]>
*/
@Slf4j
@CompileStatic
@Parameters(commandDescription = "Pushes a local implementation to a remote repository")
class CmdPush extends CmdBase implements HubOptions {

static final public NAME = 'push'

@Parameter(description = 'Repository URL to push to (optional if already configured as git remote)')
List<String> args

@Parameter(names=['-d', '-directory'], description = 'Local directory to push (default: current directory)')
String directory

@Parameter(names=['-r','-revision'], description = 'Revision of the project to run (either a git branch, tag or commit SHA number)')
String revision = 'main'

@Parameter(names=['-max-size'], description = 'Maximum file size in MB to push without confirmation (default: 10)')
int maxSizeMB = 10

@Parameter(names=['-message', '-m'], description = 'Commit message')
String message = 'Push from nextflow'

@Override
final String getName() { NAME }

@TestOnly
protected File root

@Override
void run() {
if( args && args.size() > 1){
throw new AbortOperationException('Incorrect number of arguments')
}

// Get repository from args (optional)
def repository = args && args.size() == 1 ? args[0] : null

// Folder defaults to current working directory if not specified
def folder = directory
? new File(directory).getAbsoluteFile()
: new File(System.getProperty('user.dir')).getAbsoluteFile()

if( !folder.exists() )
throw new AbortOperationException("Folder does not exist: ${folder.absolutePath}")

if( !folder.isDirectory() )
throw new AbortOperationException("Path is not a directory: ${folder.absolutePath}")

// init plugin system
Plugins.init()

try {
final manager = new PushManager(folder)
def resolvedRepo = repository
if( !resolvedRepo ) {
resolvedRepo = manager.resolveRepository()
}

log.info "Pushing folder ${folder.absolutePath} to repository ${resolvedRepo}"
manager.push(resolvedRepo, revision)
}
catch( Exception e ) {
throw new AbortOperationException("Failed to push folder: ${e.message}", e)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ class CmdRun extends CmdBase implements HubOptions {
printBanner()

// -- resolve main script
Plugins.init()
final scriptFile = getScriptFile(pipeline)

// -- load command line params
Expand Down Expand Up @@ -359,7 +360,6 @@ class CmdRun extends CmdBase implements HubOptions {
Map configParams = builder.getConfigParams()

// -- Load plugins (may register secret providers)
Plugins.init()
Plugins.load(config)

// -- Initialize real secrets system
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class Launcher {
new CmdList(),
new CmdLog(),
new CmdPull(),
new CmdPush(),
new CmdRun(),
new CmdKubeRun(),
new CmdDrop(),
Expand Down
71 changes: 68 additions & 3 deletions modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ class AssetManager {
build(pipelineName, config)
}

AssetManager(File path, String pipelineName, HubOptions cliOpts = null ) {
assert path
assert pipelineName
// build the object
def config = ProviderConfig.getDefault()
build(path, pipelineName, config, cliOpts)
}

/**
* Build the asset manager internal data structure
*
Expand All @@ -135,6 +143,22 @@ class AssetManager {
return this
}

@PackageScope
AssetManager build( File path, String pipelineName, Map config = null, HubOptions cliOpts = null ) {

this.providerConfigs = ProviderConfig.createFromMap(config)

this.project = resolveName(pipelineName)
this.localPath = path
this.hub = checkHubProvider(cliOpts)
this.provider = createHubProvider(hub)
setupCredentials(cliOpts)
validateProjectDir()

return this
}


@PackageScope
File getLocalGitConfig() {
localPath ? new File(localPath,'.git/config') : null
Expand Down Expand Up @@ -304,11 +328,13 @@ class AssetManager {

String getHub() { hub }

static boolean isUrl(String repository){
return repository.startsWith('http://') || repository.startsWith('https://') || repository.startsWith('file:/') || repository.startsWith('seqera://')
}

@PackageScope
String resolveNameFromGitUrl( String repository ) {

final isUrl = repository.startsWith('http://') || repository.startsWith('https://') || repository.startsWith('file:/')
if( !isUrl )
if( !isUrl(repository) )
return null

try {
Expand Down Expand Up @@ -685,6 +711,45 @@ class AssetManager {

}

/**
* Upload a pipeline to a remote repository
*
* @param revision The revision/branch to upload
* @param remoteName The name of the remote (default: origin)
* @param isNewRepo Whether this is a new repository initialization
* @result A message representing the operation result
*/
String upload(String revision, String remoteName = "origin", boolean isNewRepo = false) {
assert project
assert localPath

// Create and checkout branch if it doesn't exist
try {
git.checkout().setName(revision).call()
}
catch( Exception ignored ) {
// Branch doesn't exist, create it
git.checkout()
.setCreateBranch(true)
.setName(revision)
.call()
}


def pushCommand = git.push()
.setRemote(remoteName)

pushCommand.add(revision)

if( provider.hasCredentials() )
pushCommand.setCredentialsProvider( provider.getGitCredentials() )

def result = pushCommand.call()
return "pushed to ${remoteName} (${revision})"
}



/**
* Clone a pipeline from a remote pipeline repository to the specified folder
*
Expand Down
Loading
Loading