/* * Copyright 2021-2026, Seqera. * * 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 io.seqera.tower.cli.commands; import io.seqera.tower.ApiException; import io.seqera.tower.cli.commands.enums.OutputType; import io.seqera.tower.cli.commands.global.WorkspaceOptionalOptions; import io.seqera.tower.cli.commands.labels.Label; import io.seqera.tower.cli.commands.pipelines.NullableLaunchOptions; import io.seqera.tower.cli.commands.pipelines.versions.VersionRefOptions; import io.seqera.tower.cli.exceptions.InvalidResponseException; import io.seqera.tower.cli.responses.Response; import io.seqera.tower.cli.responses.runs.RunSubmited; import io.seqera.tower.model.ComputeEnvResponseDto; import io.seqera.tower.model.LaunchDbDto; import io.seqera.tower.model.ListPipelinesResponse; import io.seqera.tower.model.PipelineDbDto; import io.seqera.tower.model.SubmitWorkflowLaunchRequest; import io.seqera.tower.model.SubmitWorkflowLaunchResponse; import io.seqera.tower.model.WorkflowLaunchRequest; import io.seqera.tower.model.WorkflowStatus; import jakarta.annotation.Nullable; import picocli.CommandLine; import picocli.CommandLine.ArgGroup; import picocli.CommandLine.Command; import picocli.CommandLine.Mixin; import picocli.CommandLine.Option; import picocli.CommandLine.Parameters; import java.io.IOException; import java.nio.file.Path; import java.util.Collections; import java.util.List; import static io.seqera.tower.cli.utils.FilesHelper.readStringOrStdin; import static io.seqera.tower.cli.utils.ModelHelper.coalesce; import static io.seqera.tower.cli.utils.ModelHelper.createLaunchRequest; import static io.seqera.tower.cli.utils.ModelHelper.removeEmptyValues; import static io.seqera.tower.cli.utils.ResponseHelper.waitStatus; @Command( name = "launch", description = "Launch a pipeline" ) public class LaunchCmd extends AbstractRootCmd { @Parameters(index = "0", paramLabel = "PIPELINE_OR_URL", description = "Workspace pipeline name or pipeline URL", arity = "1") String pipeline; @CommandLine.Mixin public WorkspaceOptionalOptions workspace; @Option(names = {"--params-file"}, description = "Pipeline parameters in JSON or YAML format. Provide the path to a file containing the content. Use '-' to read from stdin.") Path paramsFile; @Option(names = {"-c", "--compute-env"}, description = "Compute environment identifier where the pipeline will run. Defaults to workspace primary compute environment if omitted. Provide the name or identifier.") String computeEnv; @Option(names = {"-n", "--name"}, description = "Custom run name for the workflow execution.") String name; @Option(names = {"--work-dir"}, description = "Work directory path where workflow intermediate files are stored. Defaults to compute environment work directory if omitted.") String workDir; @Option(names = {"-p", "--profile"}, split = ",", description = "Array of Nextflow configuration profile names to apply.") List profile; @Option(names = {"-r", "--revision"}, description = "Git revision, branch, or tag to use. Use --commit-id to pin to a specific commit within the revision.") String revision; @Option(names = {"--commit-id"}, description = "Specific Git commit hash to pin the pipeline execution to.") String commitId; // Explicit "0..1" for clarity — contrasts with the required "1" in VersionRefOptions. @Mixin won't work here as it would lose mutual exclusivity. @ArgGroup(multiplicity = "0..1") VersionRefOptions.VersionRef versionRef; @Option(names = {"--wait"}, description = "Wait until workflow reaches specified status: ${COMPLETION-CANDIDATES}") public WorkflowStatus wait; @Option(names = {"-l", "--labels"}, split = ",", description = "Labels to assign to each pipeline run. Provide comma-separated label values (use key=value format for resource labels). Labels will be created if they don't exist", converter = Label.LabelConverter.class) List