Skip to content

feat: add virtual workstation setup scripts for Linux and Windows - #271

Merged
crowecawcaw merged 29 commits into
aws-deadline:mainlinefrom
crowecawcaw:virtual-workstation-sample
Aug 3, 2026
Merged

feat: add virtual workstation setup scripts for Linux and Windows#271
crowecawcaw merged 29 commits into
aws-deadline:mainlinefrom
crowecawcaw:virtual-workstation-sample

Conversation

@crowecawcaw

@crowecawcaw crowecawcaw commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Fixes: #266

What was the problem/requirement? (What/Why)

Issue #266 asks for an example of pre-configuring a workstation for Deadline Cloud submission, so that an artist who logs in only has to sign in. Setting one up by hand means clicking through two installers, wiring a DCC plugin into per-user application preferences, and completing a monitor sign-in dialog. There was no sample showing how to do that unattended.

What was the solution? (How)

Two example scripts, one for Linux and one for Windows, under utility_scripts/virtual_workstation/. Each takes the monitor URL as its only required argument and:

  1. Installs Blender from an official release archive.
  2. Installs the Deadline Cloud submitter with its silent installer, resolved from the published submitter manifest so the download is a pinned, checksummed artifact rather than a moving "latest" URL.
  3. Enables the submitter's Blender add-on. The silent install stages the add-on but cannot enable it, because add-ons live in Blender's per-user preferences while the install runs at system scope.
  4. Installs Deadline Cloud monitor.
  5. Creates a monitor profile non-interactively with deadline-cloud-monitor create-profile.

Every download is verified against a published SHA-256 checksum, and an unreachable checksum is an error rather than a reason to skip the check. The scripts call no AWS APIs and need no credentials.

Blender is a stand-in for whichever DCC you run, chosen because it installs unattended from a public archive with no license server, which keeps the example runnable as-is. Adapting to Maya, Nuke, Houdini, 3ds Max, Cinema 4D, After Effects, or VRED means changing three marked places, called out in comments in both scripts and in the README.

Three behaviors are worth flagging for reviewers, because they are not obvious from the installers alone:

  • create-profile exits 0 even when it fails. Both scripts check its stdout for the success string and read back the [profile ...] stanza it should have written.
  • --monitor-id must be non-empty, but need not be correct. The monitor filters its profile picker on that value and drops any profile whose value is falsy, so an empty ID silently defeats the whole point: the artist gets asked for the monitor URL. The real ID cannot be discovered without AWS credentials, so the scripts pass pending-first-login, which the monitor replaces with the authoritative value at first sign-in.
  • A monitor URL without its Region segment is accepted by the monitor and produces a profile with a wrong region=, so both scripts validate the URL shape themselves first.

What is the impact of this change?

Additive: four new files and two modified. No existing sample is touched. The utility_scripts/ category table gains one row per CONTRIBUTING.md, and the static-check suite gains coverage for utility_scripts/ scripts: tests/conftest.py gets a discovery function and tests/test_utility_scripts.py runs bash -n and the PowerShell parser over them. Previously nothing under utility_scripts/ was syntax-checked in CI, though host_configuration_scripts/ was.

Scope limits, all stated in the README rather than left implicit: the Linux script targets Ubuntu 22.04, because the monitor's .deb depends on libwebkit2gtk-4.0-37, which 24.04 replaced with the 4.1 build, and no official repository offers the 4.0 build for it; both require an image that already has a desktop environment, remote access to reach it, and a working default browser; and on Windows the script must run as the artist's own account, because Windows cannot write another user's per-user state without that user's password.

How was this change tested?

Verified end to end on real EC2 instances against a real monitor, on both platforms, including a manual interactive sign-in and an authenticated API call.

Linux — Ubuntu 22.04 EC2 instance with an XFCE desktop, reached over VNC through an SSM tunnel. Ran the script, then signed in to the monitor by hand.

Before sign-in:

monitor_id=pending-first-login
user_id=
identity_store_id=
{"profile_name": "crowest-us-west-2", "status": "NEEDS_LOGIN", "api_availability": false}

After sign-in, the monitor replaced all three with authoritative values:

user_id=f8115370-70f1-70c2-f3a8-9f857c830818
identity_store_id=d-9267dc065a
monitor_id=monitor-ad9b8cfa2a32417ebb9d44567c5eb0ca
{"profile_name": "crowest-us-west-2", "status": "AUTHENTICATED", "api_availability": true}

$ deadline farm list
- region: us-west-2
  farmId: farm-3ce486c2f12a4f9584afe381615364d1
  displayName: crowest farm

Windows — Windows Server 2022 EC2 instance reached over RDP through an SSM tunnel, script run as the artist with elevation. Same result: monitor opened straight to sign-in with no URL prompt, and after signing in, monitor_id became monitor-ad9b8cfa2a32417ebb9d44567c5eb0ca, auth status reported AUTHENTICATED, and deadline farm list returned the farm.

Both instances were in private subnets with no inbound rules, reachable only through SSM port forwarding, and have been deleted.

Also tested

  • Full runs in containers on both platforms, with independent post-hoc assertions rather than trusting the scripts' own output: blender --version, the add-on read back from bpy.context.preferences.addons.keys(), deadline --version on the artist's login PATH, and the profile stanza in ~/.aws/config.
  • Checksum verification: a real archive against a multi-file manifest, a deliberately corrupted file, an unreachable checksum URL, and a filename absent from the manifest.
  • Error paths: no arguments, a monitor URL with no Region segment, a non-apt image, and an image whose repositories lack libwebkit2gtk-4.0-37.
  • Static analysis: shellcheck and PSScriptAnalyzer both clean, plus python3 scripts/validate_repository.py, python3 scripts/check_external_links.py, and Vale.

Not tested: submitting an actual job from Blender. Everything up to and including authenticated API calls is verified.

Review round: defects found and fixed after the original testing

Checking the scripts' assumptions against live package indexes and the monitor's own .deb metadata found three defects, each since fixed and re-verified end to end on fresh instances.

  • The stated scope was wrong, and the failure mode was bad. The monitor's .deb declares Depends: libwebkit2gtk-4.0-37. Launchpad shows that package is published up to Ubuntu 22.04 only; later releases carry libwebkit2gtk-4.1-0. "Debian-family" therefore over-promised: on Ubuntu 24.04 the script installed Blender and the submitter before failing at apt dependency resolution. There is now an up-front check that stops before installing anything. It uses apt-cache policy rather than apt-cache show, which also succeeds for a virtual package. The supported scope is now Ubuntu 22.04 alone: Debian 12 was listed for a while, but it was never tested, so claiming it was not something this change could back up.
  • One download skipped verification. libssl1.1 was fetched and installed with no checksum, the sole exception to a rule the README states twice. It is not published with a .sha256 beside it, so the expected hash is now a pinned constant, with a comment naming the Packages.gz index to read a newer one from.
  • The pinned OpenSSL was unpatched. It was 1.1.1f-1ubuntu2, the original 20.04 release, superseded in focal-security by 1.1.1f-1ubuntu2.24. Now on the patched build.

Confirmed the OpenSSL 1.1 requirement is real rather than inherited folklore: strings on /usr/bin/deadline-cloud-monitor shows libssl.so.1.1, and the .deb declares no SSL dependency, which is exactly why a missing library does not fail the install and instead surfaces at first launch.

Also replaced the Blender mirror. It pointed at one volunteer host (mirrors.iu13.net); it now uses Blender's own redirector, mirror.blender.org, verified to serve both the archive and the .sha256 manifest for Linux and Windows.

Re-verified on fresh EC2 instances in a private subnet with no public IP and no inbound rules, reachable only through SSM port forwarding, on Ubuntu 22.04 and Windows Server 2022. Both exited 0. Independent post-hoc assertions rather than the scripts' own output: blender --version, the add-on read back from bpy.context.preferences.addons.keys() as the artist, deadline --version on the artist's login PATH, the profile stanza with a non-empty monitor_id, and deadline auth status reporting NEEDS_LOGIN. Interactive sign-in then completed by hand on both platforms: the monitor opened straight to sign-in with no URL prompt. Both instances have been deleted.

Second review round: silent-failure fixes and verified documentation

A further review pass, plus automated review on the PR, found defects that a passing run hides. Each was reproduced before fixing.

  • The Windows script reported success while doing nothing useful when run as SYSTEM. #Requires -RunAsAdministrator is satisfied by SYSTEM, which Systems Manager Run Command and EC2 user data both run as, and every check still passed because they all read the invoking user's own state. The README documented the consequence; nothing enforced it. It now refuses, verified on a real instance: exit 1 with nothing created.
  • The Blender version check reintroduced a SIGPIPE bug on both platforms. blender --version | head -1 under pipefail, and & $blenderExe --version | Select-Object -First 1 on Windows, both let the consumer's early exit determine the reported status, so a working Blender could be reported as unable to run. Both now capture the full output and narrow it only for the message. Caught by automated review, which was right to flag it as the same class of defect the libssl check had just been fixed for.
  • Two URL validators disagreed. [System.Uri] parses the host out of any scheme, so Windows accepted http://, ftp://, and file:// and would write a non-HTTPS URL into the artist's profile, while Linux rejected the uppercase form Windows accepted. Both now check the scheme and compare in lowercase, and agree on all seven inputs tested.
  • rm -rf / Remove-Item -Recurse -Force ran unconditionally as root or administrator on a prefix constant the README tells readers to edit. Both now refuse a directory that holds no Blender executable.
  • A Blender that installed but could not start was reported as success, and --enable-components hardcoded deadline_cloud_for_blender outside the three places marked as needing changes, so following the adaptation instructions still installed the Blender submitter.
  • Windows left roughly 1 GB of installers in %TEMP%, where Linux traps and removes them. Now removed on success, and deliberately kept on failure so installer logs survive.

Every factual claim in the README was then checked against the real artifacts rather than left as inference. That corrected the cleanup steps (the Linux uninstaller exits 0 but leaves THIRD_PARTY_LICENSES behind), removed advice to add a repository that does not exist for libwebkit2gtk-4.0-37 on newer releases, and noted that deadline auth login is not an alternative to the monitor since it drives the monitor and accepts only monitor-created profiles.

Re-verified end to end on fresh Ubuntu 22.04 and Windows Server 2022 instances in a private subnet with no public IP and no inbound rules: both exited 0, Linux twice for idempotency, the Windows SYSTEM guard exited 1 creating nothing, and hiding a real DT_NEEDED library confirmed the version check still catches a genuinely broken Blender rather than having been neutered by the exit-status change. All instances have been deleted.

Was this change documented?

Yes. utility_scripts/virtual_workstation/README.md covers prerequisites, how it works, what the profile contains and why its fields start empty, adapting to another DCC, what ends up on the machine, security and cleanup, and troubleshooting for the failures this testing actually produced. utility_scripts/README.md gains the category table row and a short section, per CONTRIBUTING.md.


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@github-actions github-actions Bot added the waiting-on-maintainers Waiting on the maintainers to review. label Jul 30, 2026
Comment thread utility_scripts/virtual_workstation/setup_workstation_linux.sh Outdated
Add provisioning scripts that prepare a Linux or Windows workstation for
Deadline Cloud submission, so an artist who logs in only has to sign in.

Each script installs Blender, resolves the latest submitter installer from
the published manifest and runs it unattended after verifying its SHA-256
checksum, installs Deadline Cloud monitor, and creates a monitor profile
non-interactively with `deadline-cloud-monitor create-profile`.

Two behaviors that are not obvious from the installers alone:

* The unattended submitter install stages the Blender add-on but does not
  enable it, because add-ons live in Blender's per-user preferences. Both
  scripts run the installer's own add_submitter_to_pref.py through Blender
  in background mode and then read the preferences back to confirm.
* `create-profile` exits 0 even when it fails, so both scripts check its
  output and verify the resulting stanza in the user's AWS config.

The monitor profile and Blender preferences are per user. Linux uses
runuser so provisioning as root works; Windows cannot run as another local
user without their password, so it fails fast instead of writing the
profile into the wrong home directory.

Resolves aws-deadline#266

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Record that create-profile was added in monitor 1.0.2 for administrator
provisioning, note that the user guide documents only the interactive
wizard, and cite the GetMonitor API pattern for the monitor ID rather
than asserting the format as a fixed rule.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
…2022

Running the script end to end on an EC2 Windows Server 2022 instance
surfaced four defects, each of which made it fail or report success
falsely. Verified fixed by a clean run plus independent assertions.

* Checksum verification always failed. Windows PowerShell 5.1 returns
  Invoke-WebRequest .Content as Byte[] rather than String, so splitting
  it yielded the first byte value ("98") instead of the hash. Added a
  Get-RemoteText helper that decodes when needed, and used it for the
  manifest too.

* The submitter installer rejected the Blender path. On Windows the
  --blender-<version>-path flag expects the full path to blender.exe,
  not the install directory as on Linux.

* The installer rejected paths containing spaces. Start-Process joins
  -ArgumentList without quoting, so "C:\Program Files\..." arrived as
  two arguments. Quote the values that can contain spaces.

* Add-on verification passed unconditionally. Passing a quoted Python
  expression through --python-expr loses the inner quotes, so Blender
  raised NameError while the check still reported success. Use a script
  file instead. Blender does propagate sys.exit status, and Linux is
  unaffected because bash preserves the quoting.

Also resolve the monitor executable from the uninstall registry entry:
under a 32-bit host process the installer honors WOW64 redirection and
lands in the SysWOW64 view of the profile, which %LOCALAPPDATA% does not
point to, so the previous fixed paths could not find it.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
A review pass raised issues that were then confirmed against real images
and live endpoints.

Correctness:

* The script died on its first action on Amazon Linux 2023 and RHEL 9
  derivatives: they ship curl-minimal, which provides /usr/bin/curl but
  conflicts with the curl package, so `dnf install curl` exits 1. Verified
  on amazonlinux:2023. Require the binaries instead of the packages, and
  add python3, which the manifest parser needs and minimal images omit.

* The OpenSSL 1.1 step was gated on a major version of "9", but AL2023
  reports VERSION_ID=2023, so it never ran there. compat-openssl11 is not
  in any AL2023 repo and the monitor RPM declares no SSL dependency, so
  the install succeeded and the monitor then failed at first launch. Gate
  on the missing library instead, and fail with an explanation.

* `log "... $("$MONITOR_BIN" --version)"` could not abort under set -e, so
  a monitor that installed but could not start was reported as success.
  Capture the version in an assignment.

* The profile name was interpolated into grep patterns unescaped, so a
  name containing "." could match output the monitor never printed, which
  defeats the success check that exists because create-profile exits 0 on
  failure. Use grep -F.

* Refuse --skip-blender without --skip-submitter: it pointed the submitter
  at a Blender path that was never created.

* A trailing flag with no value exited 1 with no output at all.

Verification: the monitor packages and the Blender archive were downloaded
and executed unverified, though both publish checksums. Verify all three,
and make verification strict, since silently downgrading to no check on a
transient error defeats the purpose. Surface AWS CLI errors instead of
discarding them.

Reuse: Blender is a placeholder for other DCCs, but the Blender-specific
logic was spread across five regions with no signposting. Add an
"ADAPTING THIS SCRIPT TO A DIFFERENT DCC" header to both scripts and a
numbered DCC (n of 5) marker at each place that needs changing.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
The scripts had accumulated flags, fallbacks, and branches that obscured the
flow an administrator needs to read and adapt. Cut them back to a single
linear path, from 536 to 313 lines on Linux and 472 to 321 on Windows.

Drop the monitor ID discovery entirely. Verified in the monitor source that
sign-in calls set_credentials, which rewrites the profile with authoritative
monitor, user, and identity store IDs from the portal, and verified that
create-profile accepts --monitor-id "". The scripts now pass an empty value,
which removes the AWS CLI dependency, the deadline:ListMonitors permission,
the placeholder ID, and two warning paths. The example needs no credentials.

Stop installing OpenSSL 1.1. Verified libssl.so.1.1 is absent from Ubuntu
22.04, 24.04, and Rocky 9, so it cannot be assumed, but auto-installing it
meant a hardcoded archive.ubuntu.com URL pinned to one Ubuntu build plus an
EPEL dance that cannot work on Amazon Linux 2023. Check for the library and
stop with per-distribution instructions instead, so the requirement is the
administrator's to satisfy and is documented as a prerequisite.

Replace the flag parsers with positional arguments: the monitor URL, and on
Linux an optional workstation user. That removes the need_value helper, the
three --skip flags and the invalid combination they allowed, --profile-name,
--monitor-id, --blender-version, and --blender-mirror. Version, component,
mirror, and prefixes are now constants at the top of each file.

Collapse download plus verify into one download_verified/Get-VerifiedFile
helper, so every artifact is fetched and checked the same way in one line.

Replace the five numbered "DCC (n of 5)" markers with three, now that the
per-version component map is a single constant.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Rerunning the simplified script on a Windows Server 2022 instance caught
both of these; neither is reachable on Linux.

The empty monitor ID was passed as --monitor-id "", which PowerShell drops
entirely, so the monitor reported that the flag requires a value and no
profile was created. Use --monitor-id= instead, which both platforms accept.
The Linux script now uses the same form so the two read alike.

Resolving the monitor executable from the uninstall registry entry failed.
The installer is 32-bit, so under a service account its writes are
redirected into the SysWOW64 view of the profile while the InstallLocation
it records still names System32: the registry path does not exist on disk.
Neither source is reliable alone, so try the recorded path and its SysWOW64
equivalent, and report every candidate when none exists.

Verified end to end on Windows: exit 0, three checksums verified, add-on
enabled, deadline CLI 0.60.3, profile written and read back. Linux re-run
after the flag change with the same result.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Testing the RHEL branch for the first time showed it did not work: on Rocky 9
the submitter's Blender add-on fails to import its Qt bindings, so the add-on
never registers. Supporting it would mean documenting a list of per-distro
library packages, which is noise in an example.

Drop the RHEL branch and target Debian-family images. That removes the
distribution detection, the pkg_install indirection, the dual .deb/.rpm
monitor install, and the "do not ask for curl" workaround for curl-minimal.
A single check for apt-get fails fast on anything else, and the README says
what to change for another distribution.

With one distribution in scope, installing OpenSSL 1.1 is a single known
step again rather than a per-distro guess, so do it instead of making the
administrator satisfy it. Verified end to end on a bare Ubuntu 22.04 desktop
image with no manual preparation: exit 0, three checksums verified, add-on
enabled, deadline CLI 0.60.3, profile written and read back.

Linux is now 288 lines, down from 313.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Manual sign-in testing on real EC2 instances, against a real monitor, on
both Linux and Windows, showed the empty --monitor-id broke the one thing
this sample exists to do: the monitor ignored the pre-created profile and
asked the artist for the monitor URL.

The monitor filters its profile picker on the monitor_id value from
~/.aws/config and drops any profile whose value is falsy, so an empty ID
removes the profile from the list before auto-login is evaluated. The check
is only for non-emptiness: no format, length, or prefix is required, and
the value is not resolved against the service before sign-in. Passing
"pending-first-login" is therefore enough, and keeps the property that made
the empty value attractive, namely that no AWS credentials are needed to
discover the real ID.

Verified end to end on both platforms: the monitor opens straight to
sign-in with no URL prompt, and first sign-in replaces the placeholder with
the real monitor ID in both ~/.aws/config and the monitor's settings.json,
alongside user_id and identity_store_id. After sign-in, deadline auth
status reports AUTHENTICATED and deadline farm list returns the farm.

Also drop the --monitor-id= syntax, which existed only to smuggle an empty
value past PowerShell's argument handling. With a real value the ordinary
form works on both platforms, so the two scripts read alike again.

README: document the default-browser requirement, since the monitor hands
off to a browser to finish sign-in and Ubuntu's snap-only Firefox does not
work in a remote-desktop session; note that Windows needs an already
elevated shell because of #Requires -RunAsAdministrator; and add
troubleshooting for the monitor missing from the applications menu, which
happens because its desktop entry declares no category.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
…bssl1.1

Three problems found by checking the scripts' assumptions against live
package indexes and the monitor's own .deb metadata.

* The README's stated scope of "Debian-family images" is wrong, and the
  script's apt-get check accepts images the monitor cannot install on.
  The monitor's .deb declares Depends: libwebkit2gtk-4.0-37, which the
  Launchpad and Debian indexes show is published up to Ubuntu 22.04 and
  Debian 12 only; later releases carry libwebkit2gtk-4.1-0 instead. On
  Ubuntu 24.04 or Debian 13 the script would install Blender and the
  submitter, then fail at apt dependency resolution. Check for an
  installable candidate up front and stop with an explanation.

* libssl1.1 was downloaded and installed with no checksum, the one
  artifact in the script exempt from a rule the README states twice. It
  is not published with a .sha256 beside it, so pin the expected hash as
  a constant and name the Packages index to read a newer one from.

* The pinned libssl1.1 was 1.1.1f-1ubuntu2, the original 20.04 release,
  superseded in focal-updates and focal-security by 1.1.1f-1ubuntu2.24.
  Use the patched build.

Also point the Blender mirror at Blender's own redirector,
mirror.blender.org, rather than naming one downstream mirror. Verified
that it serves both the archive and the .sha256 manifest for Linux and
Windows, so the two scripts no longer hardcode a single volunteer host.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
@crowecawcaw
crowecawcaw force-pushed the virtual-workstation-sample branch from 00807b7 to 3f1d74a Compare July 30, 2026 23:15
Signing in by hand on both platforms surfaced four gaps between the README
and observed behavior.

* The profile section showed only the Linux credential_process, which shells
  out to cat over a cache file. Windows writes a different form entirely,
  invoking the monitor executable with get-credentials. Show both, since the
  Windows one is what an administrator debugging a Windows workstation sees.

* Nothing warned against running the Windows script as SYSTEM. Systems
  Manager Run Command and EC2 user data both execute that way, and both are
  plausible ways to reach for a provisioning script. Doing so writes the
  profile and Blender preferences into a service profile the artist never
  logs in to, so the artist sees nothing pre-configured and the failure is
  silent. Name the two mechanisms and give the scheduled-task flags that
  run it as the artist instead.

* The prerequisites asked for a desktop environment but not for the remote
  access needed to reach it, and did not say when the artist's sign-in
  happens relative to the script. State that the scripts install neither.

* The Firefox note stopped short of the apt pin, without which Ubuntu's
  snap transitional package can win and sign-in fails in a remote session.
  Record that the Mozilla .deb was verified to complete sign-in over VNC.

Also mark the monitor's install scope in the layout table: system-wide on
Linux, per user on Windows. That asymmetry is why the Windows script must
run as the artist, and the table read as though both were equivalent.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
A review pass found defects that a passing run hides, each reproduced before
fixing.

Correctness:

* The Windows script reported success after writing everything into a service
  profile no artist logs in to. #Requires -RunAsAdministrator is satisfied by
  SYSTEM, which Systems Manager Run Command and EC2 user data both run as, and
  every check still passed because they all read the invoking user's own state.
  The README already documented the consequence; nothing enforced it. Refuse to
  run as SYSTEM.

* The libssl check could report a library that is present as missing. Under
  pipefail, `ldconfig -p | grep -q` dies with SIGPIPE once ldconfig outpaces
  grep's early exit, so the pipeline returns 141. Reproduced: status 141
  whenever the match is not in the final 64 KB, which on a desktop image it is
  not. The result was a redundant download and reinstall on every re-run,
  including over a newer libssl from another source. Capture, then match.

* The two URL validators disagreed. [System.Uri] parses the host out of any
  scheme, so Windows accepted http://, ftp://, and file:// and wrote a
  non-HTTPS URL into the artist's profile, while Linux rejected the uppercase
  form Windows accepted. Check the scheme explicitly and compare in lowercase.

* `rm -rf "$BLENDER_PREFIX"` ran unconditionally as root on a constant the
  README tells readers to edit, so a prefix of /opt or C:\Program Files would
  be destroyed. Only delete a directory holding a Blender executable.

* Blender installed but unable to start was reported as success: a command
  substitution in an argument cannot abort under set -e, and `| head -1` masks
  the status regardless. Reproduced with a stub failing on a missing shared
  library. Capture in an assignment, matching what the monitor step already did.

* A failed download exited with curl's status and no error line, unlike the
  checksum fetch beside it.

Portability: --enable-components hardcoded deadline_cloud_for_blender outside
the three places marked as needing changes, so following the instructions still
installed the Blender submitter. Hoist it to SUBMITTER_COMPONENT.

Windows left roughly 1 GB of installers in %TEMP%, where Linux traps and
removes them. Remove them on success, keeping them when a run fails so the
installer logs survive.

Tests: utility_scripts/ had no CI coverage, though host_configuration_scripts/
gets bash -n and PowerShell parse checks from machinery that only needed a
second discovery function. Verified both new checks fail on injected syntax
errors. The scriptBody length limit stays scoped to host configuration, which
is the only place it applies.

README: document --enable-auto-login and --set-as-deadline-default, which
change observable behavior and were passed silently; replace troubleshooting
that sent readers to re-run the script for a state the script cannot produce;
stop recommending --python-expr on Windows, which the script itself avoids
because PowerShell drops the inner quotes; give concrete uninstall commands
for both platforms; and disclose that Debian 12 takes an untested path that
installs an Ubuntu-built libssl.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Re-running on a bare Ubuntu 22.04 server image showed the new "will not run"
check firing correctly but reporting nothing actionable: Blender was missing
libXrender, libXfixes, libXi, libxkbcommon, libSM, libICE, and libGL, and the
message said only that it would not run.

That image has no desktop environment, which the README lists as a prerequisite,
so failing is right. Report ldd's unresolved libraries and name the likely cause
so the reader can act instead of guessing which of the preceding steps broke.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Both the README and the script's error message told readers on Ubuntu 24.04 or
Debian 13 to "add a repository that provides the 4.0 build" of
libwebkit2gtk-4.0-37. Checking rather than assuming: it is absent from every
noble pocket and component (main, universe, restricted, multiverse, across
release, updates, security, and backports), and Launchpad's primary archive
carries it no later than mantic. There is no such repository to add, so the
advice reads like an escape hatch and is a dead end.

Say plainly that no official repository offers it for those releases, and give
the real alternative: install the submitter without the monitor and use an
ordinary AWS credential source. Note explicitly that `deadline auth login` is
not that alternative -- it drives the monitor and accepts only profiles the
monitor created -- because it is the obvious thing to reach for and would waste
the reader's time. Also note that going this route gives up what the sample
pre-configures, so the tradeoff is stated rather than implied.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Comment thread utility_scripts/virtual_workstation/setup_workstation_linux.sh Outdated
Swept the remaining assertions and checked each against the actual installers,
packages, and binaries rather than leaving them as inference. Most held; three
did not.

* Cleanup was incomplete. The Linux uninstaller exits 0 and removes
  /etc/profile.d/deadline.sh, so the deadline CLI does leave new login shells,
  but it leaves /opt/DeadlineCloudSubmitter behind holding THIRD_PARTY_LICENSES.
  Following the old instructions left a stray directory. Add the removal and
  say why.

* The Microsoft Edge claim was stated as fact but never checked. Soften it, and
  make the neighboring Firefox point concrete: `apt install firefox` on 22.04
  gets a transitional package (version 1:1snap1-0ubuntu2) that installs the
  snap, which is the actual trap.

* The PATH claim named the right file but not what it does. It appends
  /opt/DeadlineCloudSubmitter/DeadlineClient; say so.

Verified and left alone: the deb package name is deadline-cloud-monitor;
--blender-45-path is a real flag, confirming the derivation from the component
name; /etc/profile.d/deadline.sh exists; /opt/DeadlineCloudSubmitter/uninstall
exists and accepts --mode; create-profile's required options are exactly
--profile, --monitor-id, and --monitor-url, with --enable-auto-login and
--set-as-deadline-default optional; get-credentials is a real subcommand,
matching the Windows credential_process; and the monitor's desktop entry really
does declare `Categories=` empty, which is why it lands in no menu.

Incidentally reconfirmed the OpenSSL 1.1 dependency: on an image without it the
monitor fails with "error while loading shared libraries: libssl.so.1.1",
independently of this sample.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Comment thread utility_scripts/virtual_workstation/setup_workstation_windows.ps1 Outdated
…atforms

Automated review caught the version check reintroducing, on both platforms, the
very pitfall the libssl check was just fixed to avoid.

Linux: `blender --version | head -1` under pipefail. head exits after the first
line and closes the pipe, Blender takes SIGPIPE on its next write, and the
pipeline reports 141, so a working Blender is reported as unable to run.
Reproduced with a stub emitting 40 lines, which is the order Blender itself
emits: the pipe form returns 141 while capturing first returns 0. This was worse
than the libssl case, which needed enough output to fill the pipe buffer before
it misfired; here the consumer exits immediately, so it misfires at any size.

Windows: `& $blenderExe --version 2>&1 | Select-Object -First 1` then checking
$LASTEXITCODE. Select-Object halts the upstream pipeline once it has its object,
which can terminate a still-running native command and leave $LASTEXITCODE
reflecting the termination rather than Blender's own exit. Not reproducible on
PowerShell 7, and Windows PowerShell 5.1 was not available to test, but the
capture form is unconditionally correct and matches Linux.

Both now capture the full output, then take the first line for the message.
Verified the fixed logic still reports a genuinely broken Blender, so the check
did not lose its purpose.

Audited the rest of both scripts for the same shape. The remaining Linux
pipelines are safe: the awk with `exit` reads a here-string, so there is no
producer process to signal, and cut, paste, and awk without exit all read to
EOF. On Windows, `| Out-Null` consumes its entire input, and $LASTEXITCODE
survives it correctly for both zero and nonzero exits, verified both directions.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Debian 12 was listed as supported but never tested. The package indexes say it
should work, and the README disclosed that the libssl1.1 step installs an
Ubuntu-built .deb there, but a documented caveat on an untested platform is
still a claim this change cannot back up.

Drop Debian from the supported list and say plainly that the script was written
and tested against Ubuntu 22.04. The adaptation guidance stays, since other
Debian-family releases are likely to work and the script uses nothing
Ubuntu-specific beyond apt-get and the libssl1.1 package it fetches, but that is
now framed as the reader's own porting work rather than as support.

The webkit gate keeps its behavior; only the message narrows, since Ubuntu 22.04
is the release the sample now names. Also drop the paragraph about installing an
Ubuntu .deb onto Debian, which no longer describes a supported path.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
@crowecawcaw
crowecawcaw marked this pull request as ready for review July 31, 2026 22:34
@crowecawcaw
crowecawcaw requested a review from a team as a code owner July 31, 2026 22:34
Comment thread utility_scripts/virtual_workstation/setup_workstation_linux.sh Outdated
Comment thread utility_scripts/virtual_workstation/setup_workstation_linux.sh Outdated
Comment thread utility_scripts/virtual_workstation/README.md
Comment thread utility_scripts/virtual_workstation/setup_workstation_linux.sh Outdated
Comment thread utility_scripts/virtual_workstation/setup_workstation_windows.ps1 Outdated
Comment thread utility_scripts/virtual_workstation/setup_workstation_windows.ps1 Outdated
Comment thread tests/test_utility_scripts.py
Comment thread utility_scripts/virtual_workstation/setup_workstation_linux.sh Outdated
Three defects in the Linux script, all raised in review.

The script had no mirror-image of the Windows SYSTEM refusal. Under EC2 user
data SUDO_USER is unset, so WORKSTATION_USER resolved to root; every check
downstream reads the invoking user's own state, so all of them passed and the
script reported success with the profile in /root/.aws/config and the artist
finding nothing configured. That is the exact failure the Windows guard exists
to prevent, and the script header and README both recommended the path that
triggers it. An implicit root is now refused and an explicit one still allowed,
since a root-login container or a single-user AMI bake is a real case and naming
it makes it a choice.

The ldd diagnostic could not print either of its messages. ldd exits non-zero
for a binary it cannot recognize as dynamic -- the wrong-architecture case the
diagnostic exists for -- and under set -e that status propagated out of the
assignment and exited the script before either message. Reproduced in an
Ubuntu 22.04 container: the old construct aborts, the new one continues and
reports. The "|| true" is on the ldd alone so a genuine awk or paste failure
still surfaces.

Nothing checked the architecture. Blender's archive, the monitor's .deb, and
libssl1.1 are all pinned to x86-64, and on arm64 every download and checksum
succeeds before the binaries fail to exec. Checked up front now.

Also, the webkit and architecture gates now run before any package is
installed, which makes the "before anything is installed" comment true --
previously four packages were installed first, so on 24.04 the script installed
before refusing. apt-get update still runs first, since apt-cache policy reads
the index it refreshes.

And the EXIT trap now keeps the work directory when a run fails, so a failed
Bitrock install's own log survives, matching what the Windows script already
does. Blender is unpacked to a staging directory beside the prefix and moved
into place, so an interrupted run cannot leave a prefix that the delete guard
then refuses on every later run -- staged beside the prefix rather than in
/tmp, since a cross-filesystem mv would copy and reopen the same window.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
…ssages

Four defects in the Windows script, all raised in review.

Windows PowerShell 5.1 turns each stderr line from a native command into an
error record, which $ErrorActionPreference = "Stop" escalates to a terminating
NativeCommandError. A Blender or monitor build that writes an unrelated startup
warning to stderr -- a GPU or driver notice -- would fail the script with a .NET
error rather than reaching the exit-code check below it. Whether that happens
depends on the build and the host rather than on anything the script controls.
A Get-NativeOutput helper now relaxes the preference for the duration of each
such call, verified to leave $LASTEXITCODE intact in both directions. Applied to
all four native calls that feed $LASTEXITCODE, not only the version check: the
create-profile call had more exposure, since that command is already known to
report failure poorly.

Two error messages could not be reached. With no top-level directory in the
archive, .FullName is $null and Move-Item throws a parameter-binding error
before the "expected blender.exe" check; and Select-String on a missing
.aws\config throws ItemNotFoundException before the "profile is missing"
message. Both reproduced. The directory is now captured and checked before the
move, and the config file tested before it is read, so each message can
actually surface.

Nothing checked the architecture, though the archive and installer are both
pinned to x64 and Windows on ARM exists. Checked up front now, before roughly
1 GB of downloads.

Blender is expanded to a staging directory beside the prefix and moved into
place, so the prefix only ever exists complete. Expanding into %TEMP% and moving
was also a cross-volume copy in the common case, so an interrupted run could
leave a prefix with no blender.exe that the delete guard then refuses on every
later run.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
… argument

Four documentation gaps raised in review, each a claim the reader could only
have discovered by running the scripts.

Prerequisites said "an elevated PowerShell session on Windows", which reads as
satisfiable by any administrator. Together with the SYSTEM refusal it in fact
requires the artist's own account to be able to elevate, so a studio where
artists are standard users cannot use the script as written. That is now stated,
along with the split that does work there: the installers under any
administrator, then the add-on enable and create-profile as the artist,
unelevated, since neither needs elevation.

The Linux second argument was presented as optional. It is mandatory under EC2
user data and in an AMI bake, where there is no SUDO_USER to infer and the
script now refuses rather than configuring root.

Troubleshooting gained the recovery step for a prefix left incomplete by an
interrupted run, since the delete guard deliberately will not clear it.

x86-64 is now listed as a prerequisite rather than left implicit in three pinned
artifact names.

tests/README.md gained a row for test_utility_scripts.py. The table lists every
other area, so its silence read as "nothing validates a utility script". The row
names the contrast with the host configuration row -- same syntax checks, no
scriptBody limit, because these are not uploaded to the service -- and a new
"Beyond parsing" section explains why executing a script belongs in its own
workflow rather than in this offline suite.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Nothing ran these scripts. The static suite proves only that they parse, which
is the most it can prove about a script that installs system packages and
downloads roughly 1 GB -- executing one there would cost the suite the fast and
offline property everything else in it depends on. So this is a separate
workflow, for the same reason cdk_checks.yml is.

Ubuntu 22.04 runs in a container rather than on the ubuntu-22.04 runner label.
The sample pins 22.04 because it is the last release carrying
libwebkit2gtk-4.0-37, and that runner label began deprecation in September 2026
and is unsupported after April 2027, so pinning it would buy a job needing a
rewrite almost immediately. The container also reproduces the EC2 user data
shape exactly -- root with SUDO_USER unset -- so it asserts the new refusal
rather than just not tripping it. Pinned by digest, like every action here.

Windows runs under both powershell (5.1) and pwsh (7). 5.1 is what an artist
gets by default and is the shell whose native-command stderr and
Invoke-WebRequest Byte[] behaviors this script depends on; it also cannot be
tested on a developer's macOS machine, which is why two of the defects fixed in
this branch were reasoned about rather than reproduced.

Every assertion reads the resulting machine rather than the scripts' own output,
since the scripts self-verify and checking their exit code alone would prove
little: Blender runs, the add-on is read back from Blender's preferences as the
artist, the CLI is on the artist's login PATH, the profile has the right region
and a non-empty monitor_id, and auth status reports NEEDS_LOGIN. Both platforms
then re-run for idempotency.

The monitor URL is shape-valid but nonexistent. create-profile does not contact
it and the scripts call no AWS APIs, so no credentials and no real monitor are
needed, and a nonexistent subdomain is the stronger test: it proves the profile
is written from the URL alone.

Path-filtered and weekly. The weekly run is the main point of the cron: the
submitter and monitor are resolved as "latest", so a release can break this
sample with no commit here. Keep it out of the required status checks -- a
path-filtered run reports no status at all, and every artifact comes from a
third-party endpoint that can be down for unrelated reasons.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
… failed

Three findings from running the sample end to end in a container, which is what
the new workflow does. All three were caught by that workflow rather than
reasoned about, which is the argument for having it.

The staged extraction introduced earlier in this branch made the prefix
root-only. mktemp -d creates a directory 0700 and mv preserves that, where the
mkdir it replaced took 0755 from the umask, so the artist could not traverse
/opt/blender and the add-on step failed with "Permission denied". Blender is a
system-wide install every user runs, so the staging directory is widened before
the move.

The add-on step then discarded Blender's output and reported only "failed to
enable the Blender add-on", which is how the permission error stayed invisible
for a run. Both the enable and the verify step now report what Blender said.

The library list the workflow installs was derived rather than guessed, and the
last of it took four rounds to find, because qtpy reports any failure to import
PySide6 as "No Qt bindings could be found" -- so a missing libglib, then a
missing libfontconfig, then the missing xcb platform libraries all present as a
missing PySide6 that is in fact bundled and present. The final list comes from
the closure of unresolved libraries across the installed tree under ldd. The
sample's README documents the whole set and how to diagnose it, since a customer
on a minimal image hits exactly this and the message points the wrong way.

Verified: exit 0 with all eight independent assertions passing -- Blender runs,
the add-on reads back from Blender's preferences as the artist, the CLI is on the
artist's login PATH, the profile has the right region, a non-empty monitor_id and
artist ownership, and auth status reports NEEDS_LOGIN -- and a second run also
exits 0, which exercises the prefix guard and staged extract on a re-run.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
The first push produced a run that failed in 0 seconds with no jobs, no steps,
and no annotation, named by file path rather than by the workflow's own name.
That is a startup failure: GitHub rejected the file outright.

The cause was "shell: ${{ matrix.shell }}". No context is available in a step's
shell: key -- it is absent from the context-availability table entirely, unlike
run:, with:, env:, and working-directory:, which all permit matrix. So the
expression made the whole file invalid, and every step in the job inherited that,
not just the four that used it.

Worth recording how it got through: the JSON schema validates it (shell takes a
string, and an expression is a string) and zizmor does not look at context
availability. actionlint catches it directly, which is what found this. It is now
part of how these are checked before pushing.

The matrix survives, since testing 5.1 and 7 is the point. Each entry now names
the interpreter, the steps orchestrate under a fixed pwsh, and the script under
test is invoked explicitly via that interpreter. Passed through an env var rather
than expanded into the run body, so zizmor's template-injection audit is clean at
--persona=auditor and not merely suppressed at the default. Verified locally that
a non-zero exit propagates through the indirection, since the argument-validation
step depends entirely on that.

Each entry also reports $PSVersionTable up front, so a run's log states which
interpreter it actually exercised rather than leaving it to be inferred from the
job name.

actionlint, zizmor --persona=auditor, and the Actions JSON schema are all clean.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
The workflow file is valid now, so it ran and both jobs failed for their own
reasons. Neither was a defect in the sample -- the scripts did exactly the right
thing in both cases and the harness misreported it.

The Windows argument-validation step failed after correctly refusing all four
bad URLs, on both 5.1 and 7. Every case is *expected* to exit non-zero, so
$LASTEXITCODE still held the last refusal's code when the loop ended, and the
runner's shell wrapper propagated that as the step's status: a step that did
precisely what it should was reported red. It now exits 0 explicitly. The Linux
equivalent is unaffected, because the "if" consumes the status and the trailing
echo resets it, but it gets the same explicit exit so the invariant is deliberate
rather than incidental.

The Linux bootstrap step failed with "set: Illegal option -o pipefail". A bare
ubuntu:22.04 container has no bash on the runner's PATH for the very first step,
so Actions falls back to "sh -e {0}". That step now declares shell: sh and uses
"set -eu", and installs bash explicitly so every later step can rely on the
default. Verified by running it under sh -e in the pinned image.

The first run did confirm real things, which is the point of having it: the URL
validation refuses all four malformed inputs identically under Windows
PowerShell 5.1 and PowerShell 7 -- the 5.1 behavior that could not be tested
locally and that two of this branch's fixes were reasoned about rather than
observed.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Both Windows jobs reached the last step and failed there identically, on 5.1 and
7, with create-profile returning empty output in about 0.1 seconds.

DeadlineCloudMonitor.exe is a GUI-subsystem binary, and PowerShell does not wait
for one of those to exit. What forces the wait is the pipe into Out-String. The
Get-NativeOutput refactor earlier in this branch moved the call inside a
scriptblock, which loses that, so the call returns immediately with nothing
captured and the "Created profile" check fails against an empty string. The
direct-pipeline form is what was verified on real instances before this branch
touched it, so it goes back.

The 5.1 stderr concern that Get-NativeOutput exists for still applies here, so
$ErrorActionPreference is relaxed around just this call, in a try/finally so it
is restored even if the pipeline throws. The Blender calls keep the helper: those
are console binaries, where wrapping makes no difference and was verified.

The failure message now also reports whether .aws\config appeared. "No output" and
"no output but the profile was written anyway" are different faults, and which one
it is says whether the command ran at all -- worth knowing given the command is
already documented as exiting 0 when it fails.

Caveat: the GUI-subsystem wait behavior cannot be reproduced on macOS, where both
forms capture identically for a console process. The evidence is that both
interpreters fail the same way at the same step, that the refactor is the only
change on that line, and that the restored form is the tested one. The next run
either passes or produces a message that says which of the two faults it is.

Also fixed: the Linux job needed defaults.run.shell: bash at the job level. In a
bare container Actions resolves "sh -e {0}" for every step, not just the first, so
installing bash in step one does not change what later steps get -- the previous
push moved the "Illegal option -o pipefail" failure from the bootstrap step to the
validation step rather than fixing it. The bootstrap step still overrides back to
sh, since it is what installs bash.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Dropped the argument-validation steps. This sample is a starting point for a VM
config script, not a hardened tool, so what CI needs to prove is that a correct
run still produces a working workstation -- not that every guard rejects every
malformed input. Also removed the idempotency re-runs and the interpreter-version
step for the same reason. Halves the wall-clock and the maintenance.

Comments cut to the reasons that are not evident from the code: why a container
rather than the runner label, why shell: sh on the bootstrap step, why the
interpreter comes from run: instead of shell:. 315 lines to 159.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
echo "refused as expected: $why"
}
expect_failure "no arguments"
expect_failure "no Region segment" "https://mystudio.deadlinecloud.amazonaws.com/"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The three URL-validation cases here do not actually exercise URL validation on Linux. In the container job the shell is root with SUDO_USER unset, and the script resolves the workstation user and refuses implicit root (setup_workstation_linux.sh lines 95-105) before it validates the URL (line 107). Any expect_failure case with no second argument therefore dies at the root guard first:

  • no Region segment, scheme is not https, and wrong domain all pass no user, so they exit non-zero because of the missing workstation user, not because of the URL. The test passes for the wrong reason and gives false confidence that URL validation works.

Only user does not exist (which passes nosuchuser) and implicit root with no workstation user actually reach the branch they name. To genuinely cover URL validation, pass a second argument (for example artist, created earlier, or root as an explicit user) so the run gets past the root guard and into the URL checks, e.g. expect_failure "no Region segment" "https://.../" root.

The Windows job does not have this problem, since its arg-validation step runs as a normal user and hits URL validation directly.

uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: installer-logs-${{ matrix.exe }}
path: ${{ runner.temp }}\deadline-workstation-setup

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The log-collection path here won't match where the script actually writes. setup_workstation_windows.ps1 puts its downloads under $env:TEMP\deadline-workstation-setup (line 139), but on GitHub-hosted Windows runners $env:TEMP (C:\Users\runneradmin\AppData\Local\Temp) is a different directory from ${{ runner.temp }} / RUNNER_TEMP (typically D:\a\_temp). So on failure upload-artifact finds no files at ${{ runner.temp }}\deadline-workstation-setup and, with if-no-files-found: ignore, silently uploads nothing — defeating the diagnostic purpose of the step.

Either point the step at the same location the script uses, or set the script's $WorkDir from $env:RUNNER_TEMP when present so the two agree.

Both scripts resolved the submitter by fetching manifest.json and walking it to a
version-pathed URL. There is a per-platform "latest" path that always serves the
current release, with a .sha256 beside it, so that whole step is two lines now and
the downloads stay checksum-verified. Linux no longer needs python3 at all, which
was only ever installed to parse that manifest. The monitor already used its
dcm/latest links.

Verified all nine per-platform links and their .sha256 companions return 200. They
are in the README as a table, since anyone adapting this to RPM, AppImage, or
macOS needs the URL and it is not obvious where to find it.

Also simplified to what a sample should carry, per review: dropped the
architecture guards on both platforms, folded the argument handling down (the
Linux script now documents that the second argument matters under EC2 user data
rather than refusing to run without it), and cut comments to the reasons that are
not evident from the code. Linux is 337 lines from 356 before this branch started,
Windows 401 from 378.

Kept the prefix delete guard. It is not strictness: BLENDER_PREFIX is a constant
the reader is told to edit, and rm -rf on whatever it names, as root, is
unforgiving.

Caught while trimming: rewriting the libwebkit2gtk check as a pipe into grep -q
reintroduced exactly the SIGPIPE-under-pipefail bug the original avoided, so on
Ubuntu 22.04 it reported the package missing and refused to run. Reproduced in a
container and restored the capture-first form. Audited the other pipelines; the
only remaining early-exit consumer reads a here-string, so it has no producer to
signal.

Verified end to end in an Ubuntu 22.04 container after each change: exit 0, add-on
registered for the artist, CLI on the artist's login PATH, profile with the right
region and a non-empty monitor_id, and the prefix at 0755.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>
Vale flagged eleven findings across the two READMEs this branch touches: three
semicolon splices, two verb tricolons, two standalone demonstratives, two formal
transitions, and "elevate" as overused vocabulary. Rewritten rather than worked
around, and Vale is clean locally on all three changed files.

The reworded Windows prerequisite also reads better for the thing it is actually
saying: the script must run as an administrator and as the artist at the same
time, which is the constraint, rather than "elevated as" it.

Signed-off-by: Stephen Crowe <6042774+crowecawcaw@users.noreply.github.com>

@phil-IO-p phil-IO-p left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good!

@crowecawcaw
crowecawcaw enabled auto-merge (squash) August 3, 2026 23:08
@crowecawcaw
crowecawcaw disabled auto-merge August 3, 2026 23:15
@crowecawcaw
crowecawcaw merged commit 0377173 into aws-deadline:mainline Aug 3, 2026
14 checks passed
ZainAallii added a commit to ZainAallii/deadline-cloud-samples that referenced this pull request Aug 5, 2026
…DP issue

Flatten each per-version subfolder into a single top-level .ps1, move the
sunflower_sphere example to examples/, and consolidate all per-script
READMEs into the 3dsmax/README.md index. Fold the Autodesk ADP 'Failed to
start' known issue for 3ds Max 2027 into that README with root cause and
workaround (mirrors deadline-cloud-for-3ds-max discussion aws-deadline#271).

Signed-off-by: Zain Ali <55154081+ZainAallii@users.noreply.github.com>
ZainAallii added a commit to ZainAallii/deadline-cloud-samples that referenced this pull request Aug 5, 2026
…DP issue

Flatten each per-version subfolder into a single top-level .ps1, move the
sunflower_sphere example to examples/, and consolidate all per-script
READMEs into the 3dsmax/README.md index. Fold the Autodesk ADP 'Failed to
start' known issue for 3ds Max 2027 into that README with root cause and
workaround (mirrors deadline-cloud-for-3ds-max discussion aws-deadline#271).

Signed-off-by: Zain Ali <55154081+ZainAallii@users.noreply.github.com>
ZainAallii added a commit to ZainAallii/deadline-cloud-samples that referenced this pull request Aug 5, 2026
…DP issue

Flatten each per-version subfolder into a single top-level .ps1, move the
sunflower_sphere example to examples/, and consolidate all per-script
READMEs into the 3dsmax/README.md index. Fold the Autodesk ADP 'Failed to
start' known issue for 3ds Max 2027 into that README with root cause and
workaround (mirrors deadline-cloud-for-3ds-max discussion aws-deadline#271).

Signed-off-by: Zain Ali <55154081+ZainAallii@users.noreply.github.com>
ZainAallii added a commit to ZainAallii/deadline-cloud-samples that referenced this pull request Aug 5, 2026
…DP issue

Flatten each per-version subfolder into a single top-level .ps1, move the
sunflower_sphere example to examples/, and consolidate all per-script
READMEs into the 3dsmax/README.md index. Fold the Autodesk ADP 'Failed to
start' known issue for 3ds Max 2027 into that README with root cause and
workaround (mirrors deadline-cloud-for-3ds-max discussion aws-deadline#271).

Signed-off-by: Zain Ali <55154081+ZainAallii@users.noreply.github.com>
crowecawcaw pushed a commit that referenced this pull request Aug 5, 2026
…DP issue (#274)

Flatten each per-version subfolder into a single top-level .ps1, move the
sunflower_sphere example to examples/, and consolidate all per-script
READMEs into the 3dsmax/README.md index. Fold the Autodesk ADP 'Failed to
start' known issue for 3ds Max 2027 into that README with root cause and
workaround (mirrors deadline-cloud-for-3ds-max discussion #271).

Signed-off-by: Zain Ali <55154081+ZainAallii@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting-on-maintainers Waiting on the maintainers to review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: example of pre-configuring an EC2 instance as a virtual workstation that's set up for Deadline submission

2 participants