builder.braak.pro/config/worker/deploy/snap.py
2024-11-19 21:59:53 +01:00

175 lines
6.8 KiB
Python

# SPDX-License-Identifier: GPL-2.0-or-later
# SPDX-FileCopyrightText: 2011-2024 Blender Authors
# <pep8 compliant>
import json
import os
import worker.blender.version
import worker.deploy
import worker.utils
def package(builder: worker.deploy.CodeStoreBuilder) -> None:
dry_run = False
if builder.service_env_id == "LOCAL" and not (
builder.platform == "linux" and worker.utils.is_tool("snapcraft")
):
worker.utils.warning("Performing dry run on LOCAL service environment")
dry_run = True
elif not builder.platform == "linux":
raise Exception("Can only run snapcraft on Linux, aborting")
version_info = worker.blender.version.VersionInfo(builder)
needs_stable_grade = version_info.risk_id in ["candidate", "stable"]
grade = "stable" if needs_stable_grade else "devel"
# Clean directory
for old_package_file in builder.store_snap_dir.glob("*.tar.xz"):
worker.utils.remove_file(old_package_file)
os.makedirs(builder.store_snap_dir, exist_ok=True)
# Get input package file path
package_manifest = builder.package_dir / "manifest.json"
builds = json.loads(package_manifest.read_text())
linux_package_file_path = None
for build in builds:
if build["platform"] == "linux" and build["file_extension"] == "tar.xz":
linux_package_file_path = builder.package_dir / build["file_name"]
break
if not linux_package_file_path:
raise Exception(f"Linux package not found in [{builder.package_dir}] manifest")
source_file_path = linux_package_file_path
dest_file_path = builder.store_snap_dir / linux_package_file_path.name
worker.utils.info(f"Copy file [{source_file_path}] -> [{dest_file_path}]")
worker.utils.copy_file(source_file_path, dest_file_path)
freedesktop_path = builder.code_path / "release" / "freedesktop"
snap_source_root_path = freedesktop_path / "snap"
blender_icon_file_name = "blender.svg"
snapcraft_template_file_path = (
snap_source_root_path / "blender-snapcraft-template.yaml"
)
worker.utils.info(f"Using snap config file [{snapcraft_template_file_path}]")
snapcraft_text = snapcraft_template_file_path.read_text()
snapcraft_text = snapcraft_text.replace("@VERSION@", version_info.version)
snapcraft_text = snapcraft_text.replace("@GRADE@", grade)
snapcraft_text = snapcraft_text.replace(
"@ICON_PATH@", f"./{blender_icon_file_name}"
)
snapcraft_text = snapcraft_text.replace(
"@PACKAGE_PATH@", f"./{linux_package_file_path.name}"
)
snapcraft_file_path = builder.store_snap_dir / "snapcraft.yaml"
worker.utils.info(f"Saving snapcraft config file [{snapcraft_file_path}]")
snapcraft_file_path.write_text(snapcraft_text)
print(snapcraft_text)
snap_package_file_name = f"blender_{version_info.version}_amd64.snap"
snap_package_file_path = builder.store_snap_dir / snap_package_file_name
if snap_package_file_path.exists():
worker.utils.info(f"Clearing snap file [{snap_package_file_path}]")
worker.utils.remove_file(snap_package_file_path)
os.chdir(builder.store_snap_dir)
# Copy all required files into working folder
source_file_path = (
freedesktop_path / "icons" / "scalable" / "apps" / blender_icon_file_name
)
dest_file_path = builder.store_snap_dir / "blender.svg"
worker.utils.info(f"Copy file [{source_file_path}] -> [{dest_file_path}]")
worker.utils.copy_file(source_file_path, dest_file_path)
source_file_path = snap_source_root_path / "blender-wrapper"
dest_file_path = builder.store_snap_dir / "blender-wrapper"
worker.utils.info(f"Copy file [{source_file_path}] -> [{dest_file_path}]")
worker.utils.copy_file(source_file_path, dest_file_path)
worker.utils.call(["snapcraft", "clean", "--use-lxd"], dry_run=dry_run)
worker.utils.call(["snapcraft", "--use-lxd"], dry_run=dry_run)
worker.utils.call(
["review-tools.snap-review", snap_package_file_path, "--allow-classic"],
dry_run=dry_run,
)
if dry_run:
snap_package_file_path.write_text("Dry run dummy package file")
worker.utils.info("To test the snap package run this command")
print("sudo snap remove blender")
print(f"sudo snap install --dangerous --classic {snap_package_file_path}")
def deliver(builder: worker.deploy.CodeStoreBuilder) -> None:
dry_run = False
if builder.service_env_id == "LOCAL":
worker.utils.warning("Performing dry run on LOCAL service environment")
dry_run = True
elif not builder.platform == "linux":
raise Exception("Can only run snapcraft on Linux, aborting")
version_info = worker.blender.version.VersionInfo(builder)
branches_config = builder.get_branches_config()
is_lts = builder.track_id in branches_config.all_lts_tracks
is_latest = (
branches_config.track_major_minor_versions[builder.track_id]
== version_info.short_version
)
# Never push to stable
snap_risk_id = version_info.risk_id.replace("stable", "candidate").replace(
"alpha", "edge"
)
if snap_risk_id == "stable":
raise Exception("Delivery to [stable] channel not allowed")
snap_track_id = version_info.short_version
if is_lts:
snap_track_id += "lts"
needs_release = True
elif is_latest:
# latest/edge always vdev
snap_track_id = "latest"
needs_release = True
else:
# Push current release under development to beta or candidate
needs_release = True
# worker.utils.call(["snapcraft", "list-tracks", "blender"], dry_run=dry_run)
snap_package_file_name = f"blender_{version_info.version}_amd64.snap"
snap_package_file_path = builder.store_snap_dir / snap_package_file_name
if not snap_package_file_path.exists():
raise Exception(f"Snap file [{snap_package_file_path}] missing")
worker_config = builder.get_worker_config()
env = os.environ.copy()
env["SNAPCRAFT_STORE_CREDENTIALS"] = worker_config.snap_credentials(
builder.service_env_id
)
# If this fails, then the permissions were not set correcty with acls
worker.utils.call(["snapcraft", "status", "blender"], dry_run=dry_run, env=env)
if needs_release:
# Upload and release.
snap_channel = f"{snap_track_id}/{snap_risk_id}"
cmd = ["snapcraft", "upload", "--release", snap_channel, snap_package_file_path]
else:
# Upload only.
snap_channel = ""
cmd = ["snapcraft", "upload", snap_package_file_path]
# Some api call is making this fail, seems to be status based as we can upload and set channel
worker.utils.call(cmd, retry_count=5, retry_wait_time=120, dry_run=dry_run, env=env)
if needs_release:
worker.utils.info("To test the snap package run this command")
print(f"sudo snap refresh blender --classic --channel {snap_channel}")