<>
-
-
- To complete your GitOps configuration, follow the instructions
- below. If the YAML is not added, new installers will be deleted on
- the next GitOps run, and edited installers will cause the GitOps run
- to fail.
-
-
-
{repositoryUrl && (
- First, create the YAML file below and save it to your{" "}
- .
+ Manage in .
)}
- Make sure you reference the package YAML from your fleet YAML.
-
+
+ If you added advanced options, learn how to{" "}
+
+ .
+ >
+ }
+ />
-
- {renderDownloadFilesText({
- preInstallQuery,
- installScript,
- postInstallScript,
- uninstallScript,
- iconUrl,
- onClickPreInstallQuery: preInstallQuery
- ? onDownloadPreInstallQuery
- : undefined,
- onClickInstallScript: installScript
- ? onDownloadInstallScript
- : undefined,
- onClickPostInstallScript: postInstallScript
- ? onDownloadPostInstallScript
- : undefined,
- onClickUninstallScript: uninstallScript
- ? onDownloadUninstallScript
- : undefined,
- onClickIcon: iconUrl ? onDownloadIcon : undefined,
- hasAdvancedOptionsAvailable: !isScriptPackage && !isIosOrIpadosApp,
- isScriptPackage,
- })}
-
Done
diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/_styles.scss b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/_styles.scss
index 39fa5d8b97..20083d8a6b 100644
--- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/_styles.scss
+++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/_styles.scss
@@ -1,14 +1,13 @@
.view-yaml-modal {
overflow-wrap: anywhere; // Prevent long overflow
- .info-banner__info {
- p {
- margin: 0; // Undo weird top margin from info-banner component
- }
+ .editor__label {
+ color: $core-fleet-black;
}
+
&__form-fields {
display: flex;
flex-direction: column;
gap: $pad-medium;
}
-}
+}
\ No newline at end of file
diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tests.ts b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tests.ts
index a1e55a5244..a04a7c3f4d 100644
--- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tests.ts
+++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tests.ts
@@ -1,8 +1,6 @@
-import { render, screen } from "@testing-library/react";
import { createMockSoftwarePackage } from "__mocks__/softwareMock";
-import { noop } from "lodash";
-import { createPackageYaml, renderDownloadFilesText } from "./helpers";
+import createPackageYaml from "./helpers";
describe("createPackageYaml", () => {
const {
@@ -201,197 +199,3 @@ describe("createPackageYaml", () => {
path: ./icons/falcon-sensor-test-package-icon.png`);
});
});
-
-describe("renderYamlHelperText", () => {
- const {
- pre_install_query: preInstallQuery,
- install_script: installScript,
- post_install_script: postInstallScript,
- uninstall_script: uninstallScript,
- } = createMockSoftwarePackage();
-
- it("renders nothing if no scripts/queries are present", () => {
- // Empty to simulate 'no items'
- const { container } = render(renderDownloadFilesText({}));
- expect(container).toBeEmptyDOMElement();
- });
-
- it("renders correctly with one item", () => {
- // Only install_script present
- render(
- renderDownloadFilesText({ installScript, onClickInstallScript: noop })
- );
- expect(
- screen.getByRole("button", { name: "install script" })
- ).toBeInTheDocument();
- expect(
- screen.getByText((content) =>
- content.includes("add it to your repository using the path above.")
- )
- ).toBeInTheDocument();
- expect(screen.queryByText("and")).not.toBeInTheDocument();
- });
-
- it("renders correctly with two items", () => {
- const { container } = render(
- renderDownloadFilesText({
- installScript,
- uninstallScript,
- onClickInstallScript: noop,
- onClickUninstallScript: noop,
- })
- );
- expect(
- screen.getByRole("button", { name: "install script" })
- ).toBeInTheDocument();
- expect(
- screen.getByRole("button", { name: "uninstall script" })
- ).toBeInTheDocument();
-
- // In "Next," and "Advanced options," only
- const text = container.textContent ?? "";
- const commaCount = (text.match(/,/g) || []).length;
- expect(commaCount).toBe(2);
-
- // No oxford comma for two items
- expect(
- screen.queryByText((content) => content.includes(", and"))
- ).not.toBeInTheDocument();
- expect(
- screen.getByText((content) =>
- content.includes("add them to your repository using the paths above.")
- )
- ).toBeInTheDocument();
- });
-
- it("renders correctly with all items", () => {
- // All present (default)
- const { container } = render(
- renderDownloadFilesText({
- preInstallQuery,
- installScript,
- uninstallScript,
- postInstallScript,
- onClickPreInstallQuery: noop,
- onClickInstallScript: noop,
- onClickUninstallScript: noop,
- onClickPostInstallScript: noop,
- })
- );
- expect(
- screen.getByRole("button", { name: "pre-install query" })
- ).toBeInTheDocument();
- expect(
- screen.getByRole("button", { name: "install script" })
- ).toBeInTheDocument();
- expect(
- screen.getByRole("button", { name: "post-install script" })
- ).toBeInTheDocument();
- expect(
- screen.getByRole("button", { name: "uninstall script" })
- ).toBeInTheDocument();
-
- // In "Next," "Advanced options," and 3 more commas
- const text = container.textContent ?? "";
- const commaCount = (text.match(/,/g) || []).length;
- expect(commaCount).toBe(5);
-
- // Oxford comma for four items
- expect(
- screen.queryByText((content) => content.includes(", and"))
- ).toBeInTheDocument();
- expect(
- screen.getByText((content) =>
- content.includes("add them to your repository using the paths above.")
- )
- ).toBeInTheDocument();
- });
-
- it("renders comma correctly for three items (with Oxford comma)", () => {
- // pre_install_query, install_script, uninstall_script present
- const { container } = render(
- renderDownloadFilesText({
- preInstallQuery,
- installScript,
- uninstallScript,
- onClickPreInstallQuery: noop,
- onClickInstallScript: noop,
- onClickUninstallScript: noop,
- })
- );
-
- expect(
- screen.getByRole("button", { name: "pre-install query" })
- ).toBeInTheDocument();
- expect(
- screen.getByRole("button", { name: "install script" })
- ).toBeInTheDocument();
- expect(
- screen.getByRole("button", { name: "uninstall script" })
- ).toBeInTheDocument();
-
- // In "Next," "Advanced options," and 2 more commas
- const text = container.textContent ?? "";
- const commaCount = (text.match(/,/g) || []).length;
- expect(commaCount).toBe(4);
-
- // Oxford comma for three items
- expect(
- screen.getByText((content) => content.includes(", and"))
- ).toBeInTheDocument();
- expect(
- screen.getByText((content) =>
- content.includes("add them to your repository using the paths above.")
- )
- ).toBeInTheDocument();
- });
-
- it("does not render advanced options help text when hasAdvancedOptionsAvailable is false", () => {
- render(
- renderDownloadFilesText({
- installScript: "echo install",
- onClickInstallScript: noop,
- hasAdvancedOptionsAvailable: false,
- })
- );
-
- // Should not show the "Advanced options" instructional text
- expect(screen.queryByText(/If you edited/i)).not.toBeInTheDocument();
- expect(screen.queryByText(/Advanced options/i)).not.toBeInTheDocument();
- });
-
- it("does not render script-only fields for script packages", () => {
- // Script packages should not show download links for install_script,
- // post_install_script, uninstall_script, or pre_install_query
- const { container } = render(
- renderDownloadFilesText({
- preInstallQuery,
- installScript,
- postInstallScript,
- uninstallScript,
- onClickPreInstallQuery: noop,
- onClickInstallScript: noop,
- onClickPostInstallScript: noop,
- onClickUninstallScript: noop,
- isScriptPackage: true,
- })
- );
-
- // Should not render any download buttons for script-only fields
- expect(
- screen.queryByRole("button", { name: "pre-install query" })
- ).not.toBeInTheDocument();
- expect(
- screen.queryByRole("button", { name: "install script" })
- ).not.toBeInTheDocument();
- expect(
- screen.queryByRole("button", { name: "post-install script" })
- ).not.toBeInTheDocument();
- expect(
- screen.queryByRole("button", { name: "uninstall script" })
- ).not.toBeInTheDocument();
-
- // Container should be empty since no items should be rendered
- expect(container).toBeEmptyDOMElement();
- });
-});
diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tsx
index 62b26b859c..8060a9b8e7 100644
--- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tsx
+++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/ViewYamlModal/helpers.tsx
@@ -1,23 +1,7 @@
import React, { MouseEvent } from "react";
-import Button from "components/buttons/Button";
import { hyphenateString } from "utilities/strings/stringUtils";
-interface RenderYamlHelperText {
- installScript?: string;
- uninstallScript?: string;
- preInstallQuery?: string;
- postInstallScript?: string;
- iconUrl?: string | null;
- onClickPreInstallQuery?: (evt: MouseEvent) => void;
- onClickInstallScript?: (evt: MouseEvent) => void;
- onClickPostInstallScript?: (evt: MouseEvent) => void;
- onClickUninstallScript?: (evt: MouseEvent) => void;
- onClickIcon?: (evt: MouseEvent) => void;
- hasAdvancedOptionsAvailable?: boolean;
- isScriptPackage?: boolean;
-}
-
// Helper to join items with commas and Oxford comma before "and"
const joinWithCommasAnd = (
elements: { key: string; element: JSX.Element }[]
@@ -39,106 +23,6 @@ const joinWithCommasAnd = (
});
};
-export const renderDownloadFilesText = ({
- preInstallQuery,
- installScript,
- postInstallScript,
- uninstallScript,
- iconUrl,
- onClickPreInstallQuery,
- onClickInstallScript,
- onClickPostInstallScript,
- onClickUninstallScript,
- onClickIcon,
- hasAdvancedOptionsAvailable = true,
- isScriptPackage = false,
-}: RenderYamlHelperText): JSX.Element => {
- const items: { key: string; element: JSX.Element }[] = [];
-
- // Script packages (.sh and .ps1) should not expose install_script,
- // post_install_script, uninstall_script, or pre_install_query fields
- if (!isScriptPackage && preInstallQuery) {
- items.push({
- key: "pre-install-query",
- element: (
-
- pre-install query
-
- ),
- });
- }
- if (!isScriptPackage && installScript) {
- items.push({
- key: "install-script",
- element: (
-
- install script
-
- ),
- });
- }
- if (!isScriptPackage && uninstallScript) {
- items.push({
- key: "uninstall-script",
- element: (
-
- uninstall script
-
- ),
- });
- }
- if (!isScriptPackage && postInstallScript) {
- items.push({
- key: "post-install-script",
- element: (
-
- post-install script
-
- ),
- });
- }
- if (iconUrl) {
- items.push({
- key: "icon-url",
- element: (
-
- icon
-
- ),
- });
- }
-
- if (items.length === 0) return <>>;
-
- return (
- <>
- Next, download your {joinWithCommasAnd(items)} and add{" "}
- {items.length === 1 ? "it" : "them"} to your repository using the{" "}
- {items.length === 1 ? "path" : "paths"} above.
- {hasAdvancedOptionsAvailable && (
- <>
- {" "}
- If you edited Advanced options , download and replace the{" "}
- {items.length === 1 ? "file" : "files"} in your repository with the
- updated {items.length === 1 ? "one" : "ones"}.
- >
- )}
- >
- );
-};
-
interface CreatePackageYamlParams {
softwareTitle: string;
packageName: string;
@@ -154,7 +38,7 @@ interface CreatePackageYamlParams {
isScriptPackage?: boolean;
}
-export const createPackageYaml = ({
+const createPackageYaml = ({
softwareTitle,
packageName,
version,
@@ -224,3 +108,5 @@ export const createPackageYaml = ({
return yaml.trim();
};
+
+export default createPackageYaml;