# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-FileCopyrightText: 2011-2024 Blender Authors # # Builders for releasing Blender to stores. import pathlib import buildbot.plugins from buildbot.plugins import steps as plugins_steps from buildbot.plugins import schedulers as plugins_schedulers import conf.branches import conf.worker import pipeline.common # Timeouts. default_step_timeout_in_seconds = 60 * 60 # Tracks. track_ids = conf.branches.code_store_track_ids tracked_branch_ids = {} for track_id in track_ids: tracked_branch_ids[track_id] = conf.branches.code_tracked_branch_ids[track_id] # Properties. scheduler_properties = [ buildbot.plugins.util.ChoiceStringParameter( name="store_id", label="Store:", required=True, choices=["snap", "steam", "windows"], multiple=True, strict=True, default=["snap", "steam", "windows"], ), ] def create_deliver_binaries_windows_step(worker_config, track_id, pipeline_type): # Create step for uploading msix to download.blender.org. file_size_in_mb = 500 * 1024 * 1024 worker_source_path = pathlib.Path( f"../../../../git/blender-{track_id}/build_package" ) master_dest_path = pathlib.Path( f"{worker_config.buildbot_download_folder}/{pipeline_type}" ).expanduser() return plugins_steps.MultipleFileUpload( name="deliver-binaries", maxsize=file_size_in_mb, workdir=f"{worker_source_path}", glob=True, workersrcs=["*.msix*"], masterdest=f"{master_dest_path}", mode=0o644, url=None, description="running", descriptionDone="completed", ) def populate(ENVIRONMENT): builders = [] schedulers = [] platform_worker_names = conf.machines.fetch_platform_worker_names(ENVIRONMENT) local_worker_names = conf.machines.fetch_local_worker_names() worker_config = conf.worker.get_config(ENVIRONMENT) needs_nightly_schedulers = ENVIRONMENT == "PROD" pipeline_type = "daily" store_ids = ["steam", "snap", "windows"] print("*** Creating [code] [store] pipeline") for track_id in track_ids: triggerable_scheduler_names = [] trigger_factory = buildbot.plugins.util.BuildFactory() for store_id in store_ids: # Create build steps. pipeline_build_factory = buildbot.plugins.util.BuildFactory() step_names = [ "configure-machine", "update-code", "pull-artifacts", "package", ] if store_id == "windows": step_names += ["deliver-binaries"] else: step_names += ["deliver"] step_names += ["clean"] print(f"Creating [{track_id}] [code] [store] [{store_id}] pipeline steps") for step_name in step_names: if step_name == "deliver-binaries": step = create_deliver_binaries_windows_step( worker_config, track_id, pipeline_type ) else: args = ["--store-id", store_id, step_name] step_command = pipeline.common.create_worker_command( "code_store.py", ENVIRONMENT, track_id, args ) step = plugins_steps.ShellCommand( name=step_name, logEnviron=True, haltOnFailure=True, timeout=default_step_timeout_in_seconds, description="running", descriptionDone="completed", command=step_command, ) pipeline_build_factory.addStep(step) for master_step_name in pipeline.common.code_pipeline_master_step_names: master_step_command = ( pipeline.common.create_master_command_args.withArgs( ENVIRONMENT, track_id, pipeline_type, master_step_name, single_platform=False, ) ) # Master to archive and purge builds pipeline_build_factory.addStep( plugins_steps.MasterShellCommand( name=master_step_name, logEnviron=False, command=master_step_command, description="running", descriptionDone="completed", ) ) # Create builders. worker_group_id = ( f"windows-amd64-store-{store_id}" if store_id == "windows" else f"linux-x86_64-store-{store_id}" ) pipeline_worker_names = platform_worker_names[worker_group_id] if pipeline_worker_names: pipeline_builder_name = f"{track_id}-code-store-{store_id}" builder_tags = pipeline_builder_name.split("-") builders += [ buildbot.plugins.util.BuilderConfig( name=pipeline_builder_name, workernames=pipeline_worker_names, tags=builder_tags, factory=pipeline_build_factory, ) ] scheduler_name = f"{track_id}-code-store-{store_id}-triggerable" triggerable_scheduler_names += [scheduler_name] schedulers += [ plugins_schedulers.Triggerable( name=scheduler_name, builderNames=[pipeline_builder_name] ) ] # Create coordinator. if triggerable_scheduler_names: trigger_properties = {} trigger_factory.addStep( plugins_steps.Trigger( schedulerNames=triggerable_scheduler_names, waitForFinish=True, updateSourceStamp=False, set_properties=trigger_properties, description="running", descriptionDone="completed", ) ) coordinator_builder_name = f"{track_id}-code-store-coordinator" builder_tags = coordinator_builder_name.split("-") builders += [ buildbot.plugins.util.BuilderConfig( name=coordinator_builder_name, workernames=local_worker_names, tags=builder_tags, factory=trigger_factory, ) ] coordinator_scheduler_name = f"{track_id}-code-store-coordinator-force" schedulers += [ plugins_schedulers.ForceScheduler( name=coordinator_scheduler_name, buttonName="Trigger store build", builderNames=[coordinator_builder_name], codebases=[ buildbot.plugins.util.CodebaseParameter( codebase="", revision=None, hide=True ) ], properties=scheduler_properties, ) ] if needs_nightly_schedulers and (track_id in track_ids): nightly_scheduler_name = f"{track_id}-code-store-coordinator-nightly" nightly_properties = { "revision": "HEAD", } nightly_codebases = { "blender.git": { "repository": "", "branch": tracked_branch_ids[track_id], "revision": None, } } schedulers += [ plugins_schedulers.Nightly( name=nightly_scheduler_name, builderNames=[coordinator_builder_name], codebases=nightly_codebases, properties=nightly_properties, onlyIfChanged=False, hour=5, minute=30, ) ] return builders, schedulers