@@ -295,8 +295,47 @@ def get_pipeline_from_code(pipeline_code: str) -> dict[str, typing.Any]:
295295 return data ["pipelineByCode" ]
296296
297297
298- def create_pipeline (pipeline_name : str , functional_type : str = None , tags : list [str ] = None ):
299- """Create a pipeline using the API."""
298+ def _build_pipeline_version_input (
299+ pipeline ,
300+ pipeline_directory_path : str | Path ,
301+ name : str = None ,
302+ description : str = None ,
303+ external_link : str = None ,
304+ ) -> dict :
305+ """Build the GraphQL input to create a new pipeline version."""
306+ zip_file = generate_zip_file (pipeline_directory_path .absolute ())
307+
308+ if settings .debug :
309+ # Write zip_file to disk for debugging
310+ with open ("pipeline.zip" , "wb" ) as debug_file :
311+ debug_file .write (zip_file .read ())
312+ zip_file .seek (0 )
313+
314+ return {
315+ "name" : name ,
316+ "description" : description ,
317+ "externalLink" : external_link ,
318+ "zipfile" : base64 .b64encode (zip_file .read ()).decode ("ascii" ),
319+ "parameters" : [p .to_dict () for p in pipeline .parameters ],
320+ "timeout" : pipeline .timeout ,
321+ }
322+
323+
324+ def create_pipeline (
325+ pipeline_name : str ,
326+ pipeline_directory_path : str | Path = None ,
327+ version_name : str = None ,
328+ version_description : str = None ,
329+ version_external_link : str = None ,
330+ functional_type : str = None ,
331+ tags : list [str ] = None ,
332+ ):
333+ """Create a pipeline, optionally with its first version in a single atomic call.
334+
335+ When ``pipeline_directory_path`` is provided, the directory is zipped and sent as
336+ the first version (atomic on the backend). The returned dict then carries both the
337+ ``pipeline`` and the ``pipelineVersion`` keys; otherwise only ``pipeline`` is set.
338+ """
300339 if settings .current_workspace is None :
301340 raise NoActiveWorkspaceError
302341
@@ -311,27 +350,64 @@ def create_pipeline(pipeline_name: str, functional_type: str = None, tags: list[
311350 if tags :
312351 input_data ["tags" ] = tags
313352
353+ if pipeline_directory_path is not None :
354+ pipeline = get_pipeline (pipeline_directory_path .absolute ())
355+ input_data ["version" ] = _build_pipeline_version_input (
356+ pipeline ,
357+ pipeline_directory_path ,
358+ name = version_name ,
359+ description = version_description ,
360+ external_link = version_external_link ,
361+ )
362+
314363 data = graphql (
315364 """
316- mutation createPipeline($input: CreatePipelineInput!) {
317- createPipeline(input: $input) {
318- success
319- errors
320- pipeline {
321- id
322- code
323- name
365+ mutation createPipeline($input: CreatePipelineInput!) {
366+ createPipeline(input: $input) {
367+ success
368+ errors
369+ pipeline {
370+ id
371+ code
372+ permissions {
373+ createTemplateVersion {
374+ isAllowed
375+ }
376+ }
377+ template {
378+ id
379+ code
380+ name
381+ }
382+ }
383+ pipelineVersion {
384+ id
385+ versionName
386+ pipeline {
387+ id
388+ code
389+ permissions {
390+ createTemplateVersion {
391+ isAllowed
392+ }
393+ }
394+ template {
395+ id
396+ code
397+ name
398+ }
399+ }
400+ }
401+ }
324402 }
325- }
326- }
327- """ ,
403+ """ ,
328404 {"input" : input_data },
329405 )
330406
331407 if not data ["createPipeline" ]["success" ]:
332408 raise Exception (data ["createPipeline" ]["errors" ])
333409
334- return data ["createPipeline" ][ "pipeline" ]
410+ return data ["createPipeline" ]
335411
336412
337413def download_pipeline_sourcecode (pipeline_code , output_path : Path = None , force_overwrite = False ):
@@ -628,27 +704,18 @@ def upload_pipeline(
628704 if settings .current_workspace is None :
629705 raise NoActiveWorkspaceError
630706
631- directory = pipeline_directory_path .absolute ()
632- pipeline = get_pipeline (directory )
633- zip_file = generate_zip_file (directory )
634-
635- if settings .debug :
636- # Write zip_file to disk for debugging
637- with open ("pipeline.zip" , "wb" ) as debug_file :
638- debug_file .write (zip_file .read ())
639- zip_file .seek (0 )
640-
641- base64_content = base64 .b64encode (zip_file .read ()).decode ("ascii" )
707+ pipeline = get_pipeline (pipeline_directory_path .absolute ())
642708
643709 input_data = {
644710 "workspaceSlug" : settings .current_workspace ,
645711 "code" : target_pipeline_code ,
646- "name" : name ,
647- "description" : description ,
648- "externalLink" : link ,
649- "zipfile" : base64_content ,
650- "parameters" : [p .to_dict () for p in pipeline .parameters ],
651- "timeout" : pipeline .timeout ,
712+ ** _build_pipeline_version_input (
713+ pipeline ,
714+ pipeline_directory_path ,
715+ name = name ,
716+ description = description ,
717+ external_link = link ,
718+ ),
652719 }
653720
654721 if functional_type or pipeline .functional_type :
0 commit comments