Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
cf26a86
feat: add virtual workstation setup scripts for Linux and Windows
crowecawcaw Jul 29, 2026
feb3ca1
docs: clarify create-profile support status and monitor ID format
crowecawcaw Jul 29, 2026
65a751e
fix: correct Windows script failures found testing on Windows Server …
crowecawcaw Jul 29, 2026
f782c27
fix: address review findings on correctness, verification, and reuse
crowecawcaw Jul 29, 2026
0d36380
refactor: simplify to a worked example rather than a flexible tool
crowecawcaw Jul 29, 2026
bd2a37d
fix: correct two Windows regressions from the simplification
crowecawcaw Jul 29, 2026
2c4d5d5
refactor: target Debian-family only and install OpenSSL 1.1 again
crowecawcaw Jul 30, 2026
07597dd
fix: pass a non-empty monitor ID placeholder, not an empty one
crowecawcaw Jul 30, 2026
3f1d74a
fix: reject images without the monitor's webkit dependency, verify li…
crowecawcaw Jul 30, 2026
8738702
docs: record what end-to-end testing showed the README was missing
crowecawcaw Jul 31, 2026
e6de40c
fix: address review findings on silent failures and DCC portability
crowecawcaw Jul 31, 2026
3d4f602
fix: name the missing libraries when Blender cannot start
crowecawcaw Jul 31, 2026
295426a
docs: drop advice to add a repository that does not exist
crowecawcaw Jul 31, 2026
6067a62
docs: verify the README's factual claims against real artifacts
crowecawcaw Jul 31, 2026
0ad34f7
fix: capture Blender's version output before narrowing it, on both pl…
crowecawcaw Jul 31, 2026
da44eb2
docs: narrow the supported scope to Ubuntu 22.04
crowecawcaw Jul 31, 2026
583e1f5
Merge branch 'mainline' into virtual-workstation-sample
crowecawcaw Jul 31, 2026
c764390
fix: refuse an implicitly-resolved root, and repair the ldd diagnostic
crowecawcaw Aug 3, 2026
513325f
fix: insure native calls against 5.1 stderr, and surface reachable me…
crowecawcaw Aug 3, 2026
2b3ae13
docs: state the Windows admin requirement and the required Linux user…
crowecawcaw Aug 3, 2026
a00b7fb
ci: run the virtual workstation sample end to end on both platforms
crowecawcaw Aug 3, 2026
18639f1
fix: keep the Blender prefix world-readable, and report what actually…
crowecawcaw Aug 3, 2026
1a11405
fix(ci): the workflow was invalid -- shell: takes no expression
crowecawcaw Aug 3, 2026
8ad3de7
fix(ci): correct the two failures from the first valid run
crowecawcaw Aug 3, 2026
849cfe6
fix: do not wrap the monitor's create-profile in a scriptblock
crowecawcaw Aug 3, 2026
ef4dfde
ci: test only the happy path, and trim the comments
crowecawcaw Aug 3, 2026
1be490c
refactor: use the latest download URLs, and simplify to sample scope
crowecawcaw Aug 3, 2026
3251fdb
docs: satisfy the prose linter on the changed READMEs
crowecawcaw Aug 3, 2026
0411693
Merge branch 'mainline' into virtual-workstation-sample
crowecawcaw Aug 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,25 @@ def find_host_configuration_scripts() -> list[Path]:
return sorted(set(scripts))


def find_utility_scripts() -> list[Path]:
"""Shell / PowerShell scripts under ``utility_scripts/``.

These are run by an administrator on a workstation rather than uploaded to the
service, so the host configuration length limit does not apply to them. They
still get the same syntax checks, since a sample that does not parse is broken
for everyone who copies it.
"""
base = REPO_ROOT / "utility_scripts"
if not base.is_dir():
return []
scripts = []
for pattern in ("*.sh", "*.ps1"):
for path in base.rglob(pattern):
if not _is_excluded(path.relative_to(REPO_ROOT)):
scripts.append(path)
return sorted(set(scripts))


def find_cloudformation_templates() -> list[Path]:
"""CloudFormation templates (YAML files under ``cloudformation/``).

Expand Down
75 changes: 75 additions & 0 deletions tests/test_utility_scripts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
Comment thread
crowecawcaw marked this conversation as resolved.
"""Syntax checks for the standalone scripts under ``utility_scripts/``.

Unlike a host configuration script, these are not uploaded to the service, so the
``scriptBody`` length limit does not apply. What does apply is that they parse: a
sample that does not is broken for everyone who copies it, and these run as root or
an administrator, where a syntax error can surface halfway through an install.

The same reasoning as ``test_host_configuration_scripts.py`` applies to the tools --
``bash`` and ``pwsh`` are required, and a missing one fails rather than skips,
because a skipped check is indistinguishable from a passing one.
"""
from __future__ import annotations

import os
import subprocess
from pathlib import Path

import pytest

from conftest import find_utility_scripts, rel, require_tool

_SCRIPTS = find_utility_scripts()
_SHELL_SCRIPTS = [s for s in _SCRIPTS if s.suffix == ".sh"]
_POWERSHELL_SCRIPTS = [s for s in _SCRIPTS if s.suffix == ".ps1"]


def test_utility_scripts_discovered():
assert _SCRIPTS, "no utility scripts were discovered"


@pytest.mark.parametrize("script", _SCRIPTS, ids=rel)
def test_script_is_not_empty(script: Path):
assert script.read_text(encoding="utf-8", errors="replace").strip(), f"{rel(script)} is empty"


@pytest.mark.parametrize("script", _SHELL_SCRIPTS, ids=rel)
def test_shell_script_syntax(script: Path):
"""`bash -n` catches syntax errors without executing anything."""
bash = require_tool("bash", "install bash (present by default on Linux/macOS)")
result = subprocess.run(
[bash, "-n", str(script)], capture_output=True, text=True, timeout=30
)
assert result.returncode == 0, (
f"bash syntax check failed for {rel(script)}:\n{result.stderr}"
)


@pytest.mark.parametrize("script", _POWERSHELL_SCRIPTS, ids=rel)
def test_powershell_script_syntax(script: Path):
"""Parse each PowerShell script with the PowerShell parser (no execution)."""
pwsh = require_tool(
"pwsh",
"install PowerShell (https://learn.microsoft.com/powershell/); "
"pre-installed on GitHub-hosted runners",
)
# The script path goes through an environment variable rather than being
# interpolated into the command, so it cannot be interpreted as PowerShell.
ps_command = (
"$p = $env:PWSH_TARGET_SCRIPT; $errors = $null; "
"[System.Management.Automation.Language.Parser]::ParseFile("
"$p, [ref]$null, [ref]$errors) | Out-Null; "
"if ($errors) { $errors | ForEach-Object { Write-Output $_.ToString() }; exit 1 } "
"else { exit 0 }"
)
result = subprocess.run(
[pwsh, "-NoProfile", "-NonInteractive", "-Command", ps_command],
capture_output=True,
text=True,
timeout=60,
env={**os.environ, "PWSH_TARGET_SCRIPT": str(script)},
)
assert result.returncode == 0, (
f"PowerShell parse failed for {rel(script)}:\n{result.stdout}\n{result.stderr}"
)
15 changes: 15 additions & 0 deletions utility_scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This table covers every immediate user-selectable sample directory in `utility_s
| Sample | What it demonstrates | Start here when |
|---|---|---|
| [Upload to job attachments](upload_to_job_attachments/) | Uploading files into content-addressable job attachment storage with deduplication | Large or reused datasets should be staged before job submission |
| [Virtual workstation](virtual_workstation/) | Provisioning a Linux or Windows workstation with a DCC, the Deadline Cloud submitter, and a pre-configured monitor profile | Artists should find a submission-ready machine and only need to sign in |

## Upload to job attachments

Expand Down Expand Up @@ -38,6 +39,20 @@ python upload_to_job_attachments/upload_to_job_attachments.py \

See the [sample README](upload_to_job_attachments/) for installation, permissions, options, and manifest details.

## Virtual workstation

Example scripts for Linux and Windows prepare a workstation for Deadline Cloud submission. Each one installs Blender, then installs the Deadline Cloud submitter and monitor through their silent installers. It finishes by creating a monitor profile non-interactively, so an artist only has to sign in.

```console
# Linux, as root
sudo virtual_workstation/setup_workstation_linux.sh https://mystudio.us-west-2.deadlinecloud.amazonaws.com/

# Windows, in an elevated PowerShell session
.\virtual_workstation\setup_workstation_windows.ps1 https://mystudio.us-west-2.deadlinecloud.amazonaws.com/
```

Blender stands in for whichever DCC you run. See the [sample README](virtual_workstation/) for prerequisites, adapting the scripts to another DCC, and cleanup.

## Additional resources

* [AWS Deadline Cloud user guide](https://docs.aws.amazon.com/deadline-cloud/latest/userguide/index.html)
Expand Down
Loading
Loading