Skip to content

Python script-only packages: custom package upload UI #48394

Description

@cdcme

Related user story

#41470

Task

Add .py to the Add software > Custom package upload form and the edit-software flow so a .py file is accepted, detected as script-only (advanced options follow .sh and .ps1), shows the Python icon, and renders correctly on the software details page. The file-py graphic component already exists and is wired, so no new asset work is needed. This sub-issue consumes the py_packages source contract from the backend sub-issue and can begin from this spec before the backend merges.

Two design dev notes from the Figma Ready page shape this work:

  1. "Add tooltips with supported files for each platform" — restructure the upload form's file-type message into per-platform tooltips.
  2. "Use .py file icon on software details page" — the installer card must render file-py, not the generic file-pkg.

Upload form (frontend/pages/SoftwarePage/components/forms/PackageForm/PackageForm.tsx)

Accepted extensions (:127-128):

const ACCEPTED_EXTENSIONS =
  ".pkg,.msi,.exe,.deb,.rpm,application/gzip,.tgz,.sh,.ps1,.py,.ipa";

This single constant also enforces the replace-file extension in the edit flow (same FileUploader at :411), so no edit-only change is needed.

Script-only detection (:318), which drives hiding advanced options and the automatic-install toggle:

const isScriptPackage = ext === "sh" || ext === "ps1" || ext === "py";

Icon (getGraphicName, :62-69):

} else if (ext === "py") {
	return "file-py";
}

file-py already exists at frontend/components/graphics/FilePy.tsx, is registered in graphics/index.ts:51, and is allowed in FileUploader's ISupportedGraphicNames (:21).

Supported-types message (renderFileTypeMessage, :89-102): restructured per Dev note 1. Today it lists extensions inline. The new design shows only platform names, each a TooltipWrapper whose tip lists that platform's supported files. Tooltip copy is verbatim from Figma:

const renderFileTypeMessage = () => (
  <>
    <TooltipWrapper tipContent="Supports .pkg, .sh, and .py">macOS</TooltipWrapper>,{" "}
    <TooltipWrapper tipContent="Supports .ipa">iOS/iPadOS</TooltipWrapper>,{" "}
    <TooltipWrapper tipContent="Supports .msi, .exe, .ps1">Windows</TooltipWrapper>, or{" "}
    <TooltipWrapper tipContent="Supports .deb, .rpm, .tar.gz, .sh, and .py">Linux</TooltipWrapper>
  </>
);

This changes the message for all platforms, not just .py (visible text becomes macOS, iOS/iPadOS, Windows, or Linux).

Type and utility constants

frontend/interfaces/package_type.ts:4: add py so getExtensionFromFileName returns a valid PackageType:

const scriptOnlyPackageTypes = ["sh", "ps1", "py"] as const;

frontend/utilities/file/fileUtils.tsx:12-28: add the platform display name (matches .sh):

py: "macOS & Linux",

frontend/utilities/software_install_scripts.ts:28 and software_uninstall_scripts.ts:28: add an empty case "py" (same as .sh and .ps1) so getDefaultInstallScript and getDefaultUninstallScript do not throw "unsupported file extension":

case "sh":
case "ps1":
case "py":
	return "";

frontend/interfaces/software.ts: register the new py_packages source. Do not reuse the existing python_packages, which is for inventory-detected Python packages:

  • SCRIPT_PACKAGE_SOURCES (:339): add "py_packages".
  • NO_VERSION_OR_HOST_DATA_SOURCES (:348): add "py_packages".
  • SOURCE_TYPE_CONVERSION (:300): add py_packages: "Script-only package (macOS & Linux)" — identical phrasing to the existing sh_packages entry, and exactly what the Figma details page shows.
  • INSTALLABLE_SOURCE_PLATFORM_CONVERSION (:333): add py_packages: "linux" (mirrors sh_packages).

Details page icon (Dev note 2)

InstallerDetailsWidget.renderIcon (InstallerDetailsWidget.tsx:116) hard-returns <Graphic name="file-pkg" /> for every custom package. Dev note 2 requires the file-py icon for .py packages. The widget must learn the package source or extension (for example, pass source / extension or a precomputed graphicName from getInstallerCardInfo in helpers.ts) and return <Graphic name="file-py" /> for py_packages:

const renderIcon = () => {
  if (installerType === "app-store") { /* unchanged */ }
  if (source === "py_packages") {
    return <Graphic name="file-py" />;
  }
  return <Graphic name="file-pkg" />;
};

Scope the change to .py to match the design; .sh and .ps1 keep their current file-pkg rendering unless the team decides to extend it. file-py already exists and is allowed in the Graphic set, so no new asset is needed.

Run yarn test after editing. Coordinate with #48315: if it has merged, isScriptPackage will show advanced options for script packages, so .py inherits that automatically through the shared isScriptPackage flag with no extra work.

Condition of satisfaction

  • Upload: yarn test passes. Selecting a .py file in Add software > Custom package is accepted, shows the file-py icon, is detected as script-only, and renders advanced options identically to .sh and .ps1 (hidden today, or shown if Support advanced options for script-only packages #48315 merged).
  • File-type message (Dev note 1): the upload form shows macOS, iOS/iPadOS, Windows, or Linux, each a tooltip with the verbatim copy ("Supports .pkg, .sh, and .py" for macOS; "Supports .ipa" for iOS/iPadOS; "Supports .msi, .exe, .ps1" for Windows; "Supports .deb, .rpm, .tar.gz, .sh, and .py" for Linux). The file detail shows "macOS & Linux" for a selected .py.
  • Edit flow: replacing the file on an existing .py package only accepts another .py (enforced by ACCEPTED_EXTENSIONS).
  • Details page (Dev note 2): a .py package shows the file-py icon on the installer card and "Script-only package (macOS & Linux)" as its type, and behaves like .sh and .ps1 (no version or host data columns).
  • Tests updated: fileUtils.tests.tsx, SoftwareTitleDetailsPage/helpers.tests.ts, InstallerDetailsWidget.tests.tsx, SoftwareScriptDetailsModal.tests.tsx, and GlobalActivityItem.tests.tsx cover .py and py_packages alongside the existing script sources.
  • No new asset: confirm no new SVG was added; file-py is reused.

Metadata

Metadata

Assignees

Labels

#g-auto-patchingProduct group focused on auto patching software~frontendFrontend-related issue.~sub-taskA technical sub-task that is part of a story. (Not QA'd. Not estimated.)

Type

Fields

No fields configured for Task.

Projects

Status
🐥 Ready for review

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions