Skip to content

Allow Python script-only packages - #49070

Merged
cdcme merged 8 commits into
mainfrom
feat/41470-python-script-only
Jul 16, 2026
Merged

Allow Python script-only packages#49070
cdcme merged 8 commits into
mainfrom
feat/41470-python-script-only

Conversation

@cdcme

@cdcme cdcme commented Jul 9, 2026

Copy link
Copy Markdown
Member

Related issue: Resolves #41470

Adds support for uploading Python (.py) script-only software packages — accepted as script-only (the file contents become the install script; advanced options and automatic install follow .sh/.ps1), assigned the new py_packages source, and installable on macOS and Linux hosts across the UI, REST API, and GitOps.

Feature branch combining the backend (#48942) and frontend (#48946) sub-PRs.

Checklist for submitter

  • Changes file added for user-visible changes in changes/, orbit/changes/ or ee/fleetd-chrome/changes.
  • Input data is properly validated, SELECT * is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters.

Testing

  • Added/updated automated tests
  • QA'd all new/changed functionality manually

Summary by CodeRabbit

  • New Features
    • Added support for Python (.py) script-only software packages across UI uploads, API/self-service installs, and GitOps parsing.
    • Python installers now derive metadata correctly and render the proper Python icon, with install eligibility for macOS & Linux.
  • Bug Fixes
    • Improved installer-script validation and “supported file types” error messages to include .py (and consistent handling of related script fields/options).
  • Tests
    • Expanded unit, integration, and GitOps tests to cover Python package parsing, metadata derivation, platform/host eligibility, and UI rendering.

cdcme added 2 commits July 8, 2026 13:53
**Related issue:** Resolves #48393

Adds `.py` as an accepted script-only software package on the server —
mirroring `.sh`, assigned the new `py_packages` source and installable
on macOS and Linux hosts.

  # Checklist for submitter

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.

  ## Testing

  - [x] Added/updated automated tests
  - [x] QA'd all new/changed functionality manually
**Related issue:** Resolves #48394

Adds `.py` to the custom-package upload form and software details page,
accepted and detected as a script-only package (advanced options follow
`.sh`/`.ps1`), shown with the Python icon and per-platform file-type
tooltips, and mapped to the `py_packages` source that renders as
"Script-only package (macOS & Linux)".

  # Checklist for submitter

  - [x] Added/updated automated tests
  - [x] QA'd all new/changed functionality manually

  ## Manual QA

  - [x] Verified live in the browser against a dev server
@cdcme
cdcme requested review from a team as code owners July 9, 2026 19:15
Copilot AI review requested due to automatic review settings July 9, 2026 19:15

Copilot AI 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.

Pull request overview

Adds first-class support for uploading Python (.py) script-only software packages, treating them like existing .sh/.ps1 script packages: the uploaded file contents become install_script, the installer is stored under a new py_packages source, and installs are allowed on Linux and macOS (via the existing unix-like exception).

Changes:

  • Backend: recognize .py as a script package, map it to py_packages, store as platform=linux, and allow installs on unix-like hosts.
  • Frontend: accept .py uploads, display correct platform/tooltips, and render a Python file icon where appropriate.
  • Tests: add/extend unit, integration, and GitOps tests to cover .py upload/validation/install behavior and UI rendering.

Reviewed changes

Copilot reviewed 26 out of 27 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
server/service/testdata/software-installers/script.py Adds a .py script fixture for installer testdata.
server/service/integration_enterprise_test.go Adds integration coverage for .py upload validation and persistence behavior.
server/fleet/software_installer.go Adds py_packages source mapping, linux platform mapping, and .py script package detection.
server/fleet/software_installer_test.go Extends unit tests for .py platform/source/script-package helpers.
ee/server/service/software_installers.go Extends install platform exception to .py, adds .py to validation/error strings, script metadata mapping, and script:// validation messaging.
ee/server/service/software_installers_test.go Adds unit tests for python script validation/metadata and unix-like install allowance.
cmd/fleetctl/integrationtest/gitops/software_test.go Updates expected unsupported-file-type errors to include .py.
cmd/fleetctl/fleetctl/generate_gitops_test.go Extends GitOps generation tests to include .py script packages.
frontend/utilities/software_uninstall_scripts.ts Treats .py like other script-only packages for default uninstall-script behavior.
frontend/utilities/software_install_scripts.ts Treats .py like other script-only packages for default install-script behavior.
frontend/utilities/file/fileUtils.tsx Adds .py → “macOS & Linux” platform display mapping.
frontend/utilities/file/fileUtils.tests.tsx Adds .py coverage to file utils tests.
frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsPage.tsx Threads source through to installer details widget.
frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tsx Renders a Python file icon for py_packages.
frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareInstallerCard/InstallerDetailsWidget/InstallerDetailsWidget.tests.tsx Adds tests for Python vs generic package icon selection.
frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/LibraryItemAccordion/LibraryItemAccordion.tsx Threads source into the shared installer widget for icon selection.
frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/helpers.tests.ts Adds a test ensuring py_packages titles are treated as script packages.
frontend/pages/SoftwarePage/components/forms/PackageForm/PackageForm.tsx Accepts .py uploads, displays .py icon, and updates per-platform supported-type tooltips.
frontend/pages/SoftwarePage/components/cards/SoftwareDetailsSummary/SoftwareDetailsSummary.tsx Updates comment to reflect broader “no version/host data” sources.
frontend/pages/hosts/details/DeviceUserPage/helpers.ts Uses SCRIPT_PACKAGE_SOURCES for script-only detection (now including .py).
frontend/pages/hosts/details/DeviceUserPage/helpers.tests.ts Adds test coverage for .py script setup-step detection.
frontend/pages/DashboardPage/cards/ActivityFeed/GlobalActivityItem/GlobalActivityItem.tests.tsx Adds activity feed test coverage for .py script package statuses.
frontend/interfaces/software.ts Adds py_packages conversions and includes .py in SCRIPT_PACKAGE_SOURCES.
frontend/interfaces/setup.ts Updates comments/examples to include .py script packages.
frontend/interfaces/package_type.ts Adds "py" to script-only package types.
frontend/components/ActivityDetails/InstallDetails/SoftwareScriptDetailsModal/SoftwareScriptDetailsModal.tsx Updates comment/examples to include py_packages.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ee/server/service/software_installers.go
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This change adds Python (.py) support to script-only software packages across server, GitOps, enterprise installer flows, and frontend code. Python packages map to py_packages, target Linux, validate Python shebangs, and install on macOS and Linux hosts. Frontend support includes package types, uploads, icons, activity rendering, setup detection, and command-palette search. Tests and fixtures cover validation, installation, GitOps, integration, and display behavior.

Possibly related issues

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding Python script-only package support.
Description check ✅ Passed The description includes the related issue, feature summary, and completed testing/checklist items, so it is mostly complete.
Linked Issues check ✅ Passed The changes add .py support across upload, validation, GitOps, UI, and tests, matching the linked issue's core requirements.
Out of Scope Changes check ✅ Passed No clearly unrelated changes are evident; the diff stays focused on Python script-only package support.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/41470-python-script-only

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.77778% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.16%. Comparing base (5bd3350) to head (87d13fb).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
ee/server/service/software_installers.go 57.14% 2 Missing and 1 partial ⚠️
...ePage/components/forms/PackageForm/PackageForm.tsx 66.66% 1 Missing ⚠️
frontend/utilities/software_install_scripts.ts 0.00% 1 Missing ⚠️
frontend/utilities/software_uninstall_scripts.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #49070      +/-   ##
==========================================
- Coverage   68.17%   68.16%   -0.01%     
==========================================
  Files        3849     3856       +7     
  Lines      243469   244189     +720     
  Branches    12973    13165     +192     
==========================================
+ Hits       165989   166457     +468     
- Misses      62481    62689     +208     
- Partials    14999    15043      +44     
Flag Coverage Δ
backend 69.66% <82.35%> (+<0.01%) ⬆️
frontend 60.15% <70.00%> (-0.07%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

cdcme added 2 commits July 16, 2026 10:33
**Related issue:** Resolves #49369

Self-service install of a `.py` script-only package was rejected on
macOS hosts (`Package (.py) can be installed only on linux hosts.`)
because `SelfServiceInstallSoftwareTitle` only allowed `.sh` in the
unix-like (linux + darwin) exception. Now allows `.py` too, matching the
admin install path (`installSoftwareTitleUsingInstaller`).

# Checklist for submitter

- [x] Changes file: N/A — unreleased fix on the `#41470` feature branch;
the feature PR (#49070) carries the changes file.
- [x] Input data is properly validated (platform-gate fix only; no new
input handling, SQL, or shell interpolation).

## Testing

- [x] Added/updated automated tests —
`TestSelfServiceInstallPyScriptOnUnixLike` (linux + darwin); confirmed
it fails without the fix and passes with it.
- [x] QA'd all new/changed functionality manually — live on a macOS
host: self-service `.py` install went from HTTP 400 → 202 → `installed`
(script executed), with no regression to `.sh`/Linux/Windows behavior.
**Related issue:** Resolves #49370

`fleetctl gitops` rejected a local `path:`-referenced `.py` software
package client-side with `unsupported extension ".py"`, even though a
`url:`-referenced `.py` worked end-to-end. The package-path `switch` and
the two `HydrateToPackageLevel` gates (team-level advanced options +
icon) only recognized `.sh`/`.ps1`. They now use
`fleet.IsScriptPackage`, so `.py` is accepted — and future script types
won't drift out of sync.

# Checklist for submitter

- [x] Changes file: N/A — unreleased fix on the `#41470` feature branch;
the feature PR (#49070) carries the changes file.
- [x] Input data is properly validated (extension-gating fix only; no
new input handling, SQL, or shell interpolation).

## Testing

- [x] Added/updated automated tests — `TestScriptOnlyPackagesPathPy`
(path `.py` with team-level self-service, uninstall/post-install
scripts, pre-install query, and icon); confirmed it fails without the
fix and passes with it. Also updated a sibling test's error-string
assertion.
- [x] QA'd all new/changed functionality manually — live before/after
with the real `fleetctl` binary: unfixed → `unsupported extension
".py"`; fixed → `gitops dry run succeeded`, and a real apply persisted
the package with `source: py_packages`.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
pkg/spec/gitops.go (1)

286-302: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse isScript variable.

Since isScript is already evaluated at the beginning of the function, you can reuse it here instead of calling fleet.IsScriptPackage(ext) again.

♻️ Proposed refactor
 	// Icon should be allowed at the team level yaml for script packages which must be specified as a path
 	if spec.Icon.Path != "" {
-		if !fleet.IsScriptPackage(ext) {
+		if !isScript {
 			return packageLevel, fmt.Errorf("the software package defined in %s must not have icons, scripts, queries, URL, or hash specified at the team level", *spec.Path)
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/spec/gitops.go` around lines 286 - 302, Reuse the existing isScript
variable in the icon validation condition instead of calling
fleet.IsScriptPackage(ext) again. Keep the surrounding spec.Icon.Path validation
and behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pkg/spec/gitops.go`:
- Around line 286-302: Reuse the existing isScript variable in the icon
validation condition instead of calling fleet.IsScriptPackage(ext) again. Keep
the surrounding spec.Icon.Path validation and behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b660cea7-b66a-4d14-b6f7-6cfca35d5147

📥 Commits

Reviewing files that changed from the base of the PR and between b20862b and 0ee839c.

📒 Files selected for processing (5)
  • ee/server/service/software_installers.go
  • ee/server/service/software_installers_test.go
  • pkg/spec/gitops.go
  • pkg/spec/gitops_test.go
  • pkg/spec/testdata/software/script-only.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • ee/server/service/software_installers_test.go
  • ee/server/service/software_installers.go

**Related issue:** Resolves #49371

Typing `py` (or `python`) in the command palette didn't surface **Add
custom package**, even though `.py` is now an accepted custom-package
upload type. The `add-custom-package` entry's `keywords` list enumerated
every other extension (`pkg`, `ipa`, `msi`, `exe`, `ps1`, `deb`, `rpm`,
`tar.gz`, `sh`) but omitted `py`. Added `py` and `python`.

# Checklist for submitter

- [x] Changes file: N/A — unreleased fix on the `#41470` feature branch;
the feature PR (#49070) carries the changes file.

## Testing

- [x] Added/updated automated tests — new `helpers.tests.ts` case
asserting the `add-custom-package` entry surfaces on `py`/`python`;
confirmed it fails without the fix and passes with it.
- [x] QA'd all new/changed functionality manually — live in the browser:
with a team selected, searching `py` in the command palette now lists
**Add custom package**.

<img width="1914" height="518" alt="Screenshot 2026-07-15 at 20 35 23"
src="https://github.com/user-attachments/assets/bd764e9a-0389-4f29-a77f-5f77b5090677"
/>

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
frontend/components/CommandPalette/helpers.tests.ts (1)

330-341: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Exercise the actual palette search path.

This test verifies keyword registration, but it never searches for py or python; it would pass even if keyword matching were broken. Invoke the real best-match/filtering logic with both queries and assert that add-custom-package is returned.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/components/CommandPalette/helpers.tests.ts` around lines 330 - 341,
Update the test for “surfaces Add custom package when searching py / python” to
exercise the actual palette best-match/filtering path instead of only inspecting
keywords. Run the search with both “py” and “python” queries and assert each
result includes the “add-custom-package” item, while preserving the existing
team context.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@frontend/components/CommandPalette/helpers.tests.ts`:
- Around line 330-341: Update the test for “surfaces Add custom package when
searching py / python” to exercise the actual palette best-match/filtering path
instead of only inspecting keywords. Run the search with both “py” and “python”
queries and assert each result includes the “add-custom-package” item, while
preserving the existing team context.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 174c1abd-2521-40df-a560-5c6c957ef36d

📥 Commits

Reviewing files that changed from the base of the PR and between 0ee839c and 8814a6f.

📒 Files selected for processing (2)
  • frontend/components/CommandPalette/groups/commands.ts
  • frontend/components/CommandPalette/helpers.tests.ts

@RachelElysia RachelElysia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🔥🔥🔥🔥

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow Python script-only packages

4 participants