Skip to content

Commit 79b95ef

Browse files
committed
Refactor Houdini CICD to use houdini launcher
1 parent 4807a0b commit 79b95ef

File tree

1 file changed

+130
-84
lines changed

1 file changed

+130
-84
lines changed

.github/scripts/houdini.py

Lines changed: 130 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import argparse
2-
import hashlib
32
import logging
43
import os
54
import pathlib
65
import platform
76
import re
8-
import requests
97
import shutil
10-
import sidefx
8+
import stat
119
import subprocess
12-
import tarfile
10+
from typing import Literal
1311

12+
import requests
13+
import sidefx
1414

1515
SIDEFX_CLIENT_ID = os.environ.get("SIDEFX_CLIENT_ID", "")
1616
SIDEFX_CLIENT_SECRET_KEY = os.environ.get("SIDEFX_CLIENT_SECRET_KEY", "")
@@ -19,7 +19,7 @@
1919
logging.basicConfig(format="%(asctime)s %(message)s", datefmt="%m/%d/%Y %I:%M:%S %p")
2020

2121

22-
def create_sidefx_service(client_id, client_secret_key):
22+
def create_sidefx_service(client_id: str, client_secret_key: str):
2323
"""Get the SideFX API service
2424
Args:
2525
client_id (str): The client id
@@ -35,7 +35,7 @@ def create_sidefx_service(client_id, client_secret_key):
3535
)
3636

3737

38-
def get_sidefx_platform():
38+
def get_sidefx_platform() -> Literal["win64"] | Literal["macos"] | Literal["linux"]:
3939
"""Get the active platform usable for SideFX platform API calls
4040
Returns:
4141
str: The active platform
@@ -50,8 +50,7 @@ def get_sidefx_platform():
5050
raise Exception(f"Platform not supported: {current_platform}")
5151

5252

53-
54-
def download_sidefx_product_release(dir_path, release):
53+
def download_sidefx_product_release(dir_path: str, release: dict) -> str:
5554
"""Download the release to the directory
5655
Args:
5756
dir_path (str): The target directory
@@ -77,15 +76,31 @@ def download_sidefx_product_release(dir_path, release):
7776
# download_file_hash.update(chunk)
7877
# if download_file_hash.hexdigest() != release["hash"]:
7978
# raise Exception("Checksum does not match!")
79+
os.chmod(
80+
download_file_path,
81+
stat.ST_MODE
82+
| stat.S_IEXEC
83+
| stat.S_IXUSR
84+
| stat.S_IXGRP
85+
| stat.S_IRUSR
86+
| stat.S_IRGRP,
87+
)
88+
8089
return download_file_path
8190

8291

83-
def install_sidefx_product(product, version):
92+
def install_sidefx_product(product: str, version: str) -> None:
8493
"""Install a production release of Houdini
8594
Args:
8695
product (str): The target product name (e.g. houdini, houdini-py39, etc.)
8796
version (str|None): The target product version (e.g. 20.0, 19.5, etc.)
8897
"""
98+
99+
# Create downloads directory
100+
downloads_dir_path = os.path.join(os.path.expanduser("~"), "Downloads")
101+
if not os.path.isdir(downloads_dir_path):
102+
os.makedirs(downloads_dir_path)
103+
89104
# Connect to SideFX API
90105
logging.info("Connecting to SideFX API")
91106
sidefx_service = create_sidefx_service(SIDEFX_CLIENT_ID, SIDEFX_CLIENT_SECRET_KEY)
@@ -119,61 +134,83 @@ def install_sidefx_product(product, version):
119134
"No Houdini version found for requested version | {}".format(version)
120135
)
121136

122-
target_release_download = sidefx_service.download.get_daily_build_download(
123-
product=target_release["product"],
124-
version=target_release["version"],
125-
build=target_release["build"],
126-
platform=target_release["platform"],
137+
# Install Houdini through launcher
138+
logging.info("Downloading Houdini Launcher")
139+
140+
houdini_launcher_releases_list = sidefx_service.download.get_daily_builds_list(
141+
product="houdini-launcher",
142+
version=None,
143+
platform=sidefx_platform,
144+
only_production=True,
127145
)
146+
if not houdini_launcher_releases_list:
147+
raise Exception("No 'houdini-launcher' releases found!")
128148

129-
# Download latest production release
130-
logging.info(
131-
"Downloading Houdini build {version}.{build}".format(
132-
version=target_release["version"], build=target_release["build"]
149+
houdini_launcher_target_release = houdini_launcher_releases_list[0]
150+
houdini_launcher_target_release_download = (
151+
sidefx_service.download.get_daily_build_download(
152+
product=houdini_launcher_target_release["product"],
153+
version=houdini_launcher_target_release["version"],
154+
build=houdini_launcher_target_release["build"],
155+
platform=houdini_launcher_target_release["platform"],
133156
)
134157
)
135-
downloads_dir_path = os.path.join(os.path.expanduser("~"), "Downloads")
136-
if not os.path.isdir(downloads_dir_path):
137-
os.makedirs(downloads_dir_path)
138-
houdini_installer_file_path = download_sidefx_product_release(
139-
downloads_dir_path, target_release_download
158+
159+
houdini_launcher_installer_file_path = download_sidefx_product_release(
160+
downloads_dir_path, houdini_launcher_target_release_download
140161
)
141-
# Install latest production release
142-
logging.info(
143-
"Installing Houdini build {version}.{build}".format(
144-
version=target_release["version"], build=target_release["build"]
162+
163+
license_file_path = os.path.join(downloads_dir_path, "sidefx_settings.ini")
164+
with open(license_file_path, "w") as license_file:
165+
license_file.write(
166+
f"client_id={SIDEFX_CLIENT_ID}\nclient_secret={SIDEFX_CLIENT_SECRET_KEY}\n"
167+
)
168+
169+
# Currently the API and the installer consume different syntaxes for product and build option
170+
cmd_flags = ["install"]
171+
if "-" in target_release["product"]:
172+
target_release_product, target_release_build_type = target_release[
173+
"product"
174+
].split("-")
175+
cmd_flags.extend(
176+
[
177+
"--product",
178+
target_release_product,
179+
"--build-option",
180+
target_release_build_type,
181+
]
145182
)
183+
else:
184+
cmd_flags.extend(["--product", target_release["product"]])
185+
cmd_flags.extend(
186+
[
187+
"--version",
188+
f"{target_release['version']}.{target_release['build']}",
189+
"--platform",
190+
target_release["platform"],
191+
"--settings-file",
192+
license_file_path,
193+
"--accept-EULA",
194+
"SideFX-2021-10-13",
195+
]
146196
)
147197
hfs_dir_path = ""
148198
if sidefx_platform == "linux":
149-
# Unpack tar file
150-
with tarfile.open(houdini_installer_file_path) as tar_file:
151-
tar_file.extractall(downloads_dir_path)
152-
os.remove(houdini_installer_file_path)
153-
# Get folder name
154-
houdini_installer_dir_name = target_release_download["filename"]
155-
houdini_installer_dir_name = houdini_installer_dir_name.replace(".tar", "")
156-
houdini_installer_dir_name = houdini_installer_dir_name.replace(".gz", "")
157-
houdini_installer_dir_path = os.path.join(
158-
downloads_dir_path, houdini_installer_dir_name
199+
cmd = [houdini_launcher_installer_file_path]
200+
status = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
201+
if status.returncode != 0:
202+
raise Exception(
203+
"Failed to install Houdini Launcher, ran into the following error:\n {error}".format(
204+
error=status.stderr
205+
)
206+
)
207+
logging.info(
208+
"Installing Houdini build {version}.{build}".format(
209+
version=target_release["version"], build=target_release["build"]
210+
)
159211
)
160-
cmd = [
161-
os.path.join(houdini_installer_dir_path, "houdini.install"),
162-
"--auto-install",
163-
"--accept-EULA",
164-
"2021-10-13",
165-
"--install-houdini",
166-
"--no-install-license",
167-
"--no-install-avahi",
168-
"--no-install-hqueue-server",
169-
"--no-install-hqueue-client",
170-
"--no-install-menus",
171-
"--no-install-bin-symlink",
172-
"--no-install-engine-maya",
173-
"--no-install-engine-unity",
174-
"--no-install-engine-unreal",
175-
"--no-install-sidefxlabs",
176-
]
212+
cmd = ["/opt/sidefx/launcher/bin/houdini_installer"]
213+
cmd.extend(cmd_flags)
177214
status = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
178215
if status.returncode != 0:
179216
raise Exception(
@@ -187,21 +224,24 @@ def install_sidefx_product(product, version):
187224
)
188225
hfs_symlink_dir_path = os.path.join(os.path.dirname(hfs_dir_path), "hfs")
189226
elif sidefx_platform == "win64":
190-
cmd = [
191-
houdini_installer_file_path,
192-
"/S",
193-
"/AcceptEULA=2021-10-13",
194-
"/MainApp",
195-
"/LicenseServer=No",
196-
"/StartMenu=No",
197-
"/HQueueServer=No",
198-
"/HQueueClient=No",
199-
"/EngineMaya=No",
200-
"/Engine3dsMax",
201-
"/EngineUnity",
202-
"/EngineUnreal=No",
203-
"/SideFXLabs=No",
204-
]
227+
status = subprocess.run(
228+
[houdini_launcher_installer_file_path, "/S"],
229+
stdout=subprocess.PIPE,
230+
stderr=subprocess.PIPE,
231+
)
232+
if status.returncode != 0:
233+
raise Exception(
234+
"Failed to install Houdini Launcher, ran into the following error:\n {error}".format(
235+
error=status.stderr
236+
)
237+
)
238+
logging.info(
239+
"Installing Houdini build {version}.{build}".format(
240+
version=target_release["version"], build=target_release["build"]
241+
)
242+
)
243+
cmd = [r"C:\Program Files\SideFX\launcher\bin\houdini_installer.exe"]
244+
cmd.extend(cmd_flags)
205245
status = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
206246
if status.returncode != 0:
207247
raise Exception(
@@ -210,16 +250,13 @@ def install_sidefx_product(product, version):
210250
)
211251
)
212252
hfs_dir_path = os.path.join(
213-
"C:\Program Files\Side Effects Software",
253+
r"C:\Program Files\Side Effects Software",
214254
"Houdini {}.{}".format(target_release["version"], target_release["build"]),
215255
)
216-
hfs_symlink_dir_path = os.path.join(
217-
os.path.dirname(hfs_dir_path), "Houdini"
218-
)
256+
hfs_symlink_dir_path = os.path.join(os.path.dirname(hfs_dir_path), "Houdini")
219257
else:
220258
raise Exception(
221-
"Platform {platform} is currently not"
222-
"supported!".format(platform=platform)
259+
"Platform {platform} is currently not supported!".format(platform=platform)
223260
)
224261
# Create version-less symlink
225262
logging.info(
@@ -230,15 +267,20 @@ def install_sidefx_product(product, version):
230267
os.symlink(hfs_dir_path, hfs_symlink_dir_path)
231268

232269

233-
def create_sidefx_houdini_artifact(artifact_src, artifact_dst, artifact_prefix, artifact_product_name):
270+
def create_sidefx_houdini_artifact(
271+
artifact_src: str,
272+
artifact_dst: str,
273+
artifact_prefix: str,
274+
artifact_product_name: str,
275+
) -> None:
234276
"""Create a .zip artifact based on the source directory content.
235277
The output name will have will end in the houdini build name.
236278
237279
Args:
238280
artifact_src (str): The source directory
239281
artifact_dst (str): The target directory
240282
artifact_prefix (str): The file name prefix, the suffix will be the Houdini build name
241-
artifact_product_name (str): The file name product name.
283+
artifact_product_name (str): The file name product name.
242284
This defines the Houdini product name, e.g. like 'houdini-py39'
243285
Returns:
244286
str: The artifact file path
@@ -249,16 +291,16 @@ def create_sidefx_houdini_artifact(artifact_src, artifact_dst, artifact_prefix,
249291
hfs_build_name = os.path.basename(pathlib.Path("/opt/hfs").resolve())
250292
elif sidefx_platform == "win64":
251293
hfs_build_name = os.path.basename(
252-
pathlib.Path("C:\Program Files\Side Effects Software\Houdini").resolve()
294+
pathlib.Path(r"C:\Program Files\Side Effects Software\Houdini").resolve()
253295
)
254296
else:
255297
raise Exception(
256-
"Platform {platform} is currently not"
257-
"supported!".format(platform=platform)
298+
"Platform {platform} is currently notsupported!".format(platform=platform)
258299
)
259300
hfs_build_name = re_digitdot.sub("", hfs_build_name)
260301
artifact_file_path = os.path.join(
261-
artifact_dst, f"{artifact_prefix}_{artifact_product_name}-{hfs_build_name}-{sidefx_platform}"
302+
artifact_dst,
303+
f"{artifact_prefix}_{artifact_product_name}-{hfs_build_name}-{sidefx_platform}",
262304
)
263305
artifact_dir_path = os.path.dirname(artifact_file_path)
264306
if not os.path.exists(artifact_dir_path):
@@ -287,10 +329,14 @@ def create_sidefx_houdini_artifact(artifact_src, artifact_dst, artifact_prefix,
287329
# Execute
288330
# Install Houdini
289331
if args.install:
290-
install_sidefx_product(args.install_houdini_product_name,
291-
args.install_houdini_product_version)
332+
install_sidefx_product(
333+
args.install_houdini_product_name, args.install_houdini_product_version
334+
)
292335
# Create artifact tagged with Houdini build name (expects Houdini to be installed via the above install command)
293336
if args.artifact:
294337
create_sidefx_houdini_artifact(
295-
args.artifact_src, args.artifact_dst, args.artifact_prefix, args.artifact_product_name
338+
args.artifact_src,
339+
args.artifact_dst,
340+
args.artifact_prefix,
341+
args.artifact_product_name,
296342
)

0 commit comments

Comments
 (0)