Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add app params for image builders #3511

Open
wants to merge 6 commits into
base: build/session-env-builders
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion client/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ echo " HOMEPAGE=${HOMEPAGE}"
echo " CORE_API_VERSION_CONFIG=${CORE_API_VERSION_CONFIG}"
echo " USER_PREFERENCES_MAX_PINNED_PROJECTS=${USER_PREFERENCES_MAX_PINNED_PROJECTS}"
echo " SESSION_CLASS_EMAIL_US=${SESSION_CLASS_EMAIL_US}"
echo " IMAGE_BUILDERS_ENABLED=${IMAGE_BUILDERS_ENABLED}"
echo "==================================================="

echo "Privacy file contains the following markdown (first 5 lines):"
Expand Down Expand Up @@ -82,7 +83,8 @@ tee > "${NGINX_PATH}/config.json" << EOF
"HOMEPAGE": ${HOMEPAGE},
"CORE_API_VERSION_CONFIG": ${CORE_API_VERSION_CONFIG},
"USER_PREFERENCES_MAX_PINNED_PROJECTS": ${USER_PREFERENCES_MAX_PINNED_PROJECTS},
"SESSION_CLASS_EMAIL_US": ${SESSION_CLASS_EMAIL_US}
"SESSION_CLASS_EMAIL_US": ${SESSION_CLASS_EMAIL_US},
"IMAGE_BUILDERS_ENABLED": "${IMAGE_BUILDERS_ENABLED}"
}
EOF
echo "config.json created in ${NGINX_PATH}"
Expand Down
3 changes: 2 additions & 1 deletion client/run-telepresence.sh
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ tee > ./public/config.json << EOF
"datasetSlug": "${HOMEPAGE_DATASET_SLUG}"
},
"USER_PREFERENCES_MAX_PINNED_PROJECTS": ${USER_PREFERENCES_MAX_PINNED_PROJECTS:-5},
"SESSION_CLASS_EMAIL_US": { "enabled": false }
"SESSION_CLASS_EMAIL_US": { "enabled": false },
"IMAGE_BUILDERS_ENABLED": true
}
EOF

Expand Down
32 changes: 29 additions & 3 deletions client/src/features/sessionsV2/SessionView/EnvironmentCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@
import { SerializedError } from "@reduxjs/toolkit";
import { FetchBaseQueryError, skipToken } from "@reduxjs/toolkit/query";
import cx from "classnames";
import { ReactNode, useCallback, useEffect, useMemo, useState } from "react";
import {
ReactNode,
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from "react";
import {
Bricks,
CircleFill,
Expand Down Expand Up @@ -49,6 +56,8 @@ import { ErrorLabel } from "../../../components/formlabels/FormLabels";
import { Loader } from "../../../components/Loader";
import { type ILogs, EnvironmentLogsPresent } from "../../../components/Logs";
import ScrollableModal from "../../../components/modal/ScrollableModal";
import AppContext from "../../../utils/context/appContext";
import { DEFAULT_APP_PARAMS } from "../../../utils/context/appParams.constants";
import useAppDispatch from "../../../utils/customHooks/useAppDispatch.hook";
import { toHumanDateTime } from "../../../utils/helpers/DateTimeUtils";
import PermissionsGuard from "../../permissionsV2/PermissionsGuard";
Expand All @@ -69,6 +78,10 @@ import { BUILDER_IMAGE_NOT_READY_VALUE } from "../session.constants";
import { safeStringify } from "../session.utils";

export function EnvironmentCard({ launcher }: { launcher: SessionLauncher }) {
const { params } = useContext(AppContext);
const imageBuildersEnabled =
params?.IMAGE_BUILDERS_ENABLED ?? DEFAULT_APP_PARAMS.IMAGE_BUILDERS_ENABLED;

const environment = launcher.environment;

if (!environment) {
Expand All @@ -78,7 +91,8 @@ export function EnvironmentCard({ launcher }: { launcher: SessionLauncher }) {
const { environment_kind, name } = environment;
const cardName = environment_kind === "GLOBAL" ? name || "" : launcher.name;

const buildActions = launcher.environment.environment_kind === "CUSTOM" &&
const buildActions = imageBuildersEnabled &&
launcher.environment.environment_kind === "CUSTOM" &&
launcher.environment.environment_image_source === "build" && (
<BuildActions launcher={launcher} />
);
Expand Down Expand Up @@ -217,14 +231,18 @@ function CustomBuildEnvironmentValues({
}: {
launcher: SessionLauncher;
}) {
const { params } = useContext(AppContext);
const imageBuildersEnabled =
params?.IMAGE_BUILDERS_ENABLED ?? DEFAULT_APP_PARAMS.IMAGE_BUILDERS_ENABLED;

const { environment } = launcher;

const {
data: builds,
isLoading,
error,
} = useGetBuildsQuery(
environment.environment_image_source === "build"
imageBuildersEnabled && environment.environment_image_source === "build"
? { environmentId: environment.id }
: skipToken
);
Expand Down Expand Up @@ -268,6 +286,14 @@ function CustomBuildEnvironmentValues({
<ReadyStatusBadge />
)}
</EnvironmentRow>
{!imageBuildersEnabled && (
<EnvironmentRow>
<p className={cx("mb-0", "alert", "alert-danger")}>
This session environment is not currently supported by this instance
of RenkuLab. Contact an administrator to learn more.
</p>
</EnvironmentRow>
)}
<EnvironmentRow>
{isLoading ? (
<span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,21 @@

import { skipToken } from "@reduxjs/toolkit/query";
import cx from "classnames";
import { useMemo } from "react";
import { useContext, useMemo } from "react";
import { type Control } from "react-hook-form";

import { WarnAlert } from "../../../../components/Alert";
import { ErrorAlert, WarnAlert } from "../../../../components/Alert";
import { Loader } from "../../../../components/Loader";
import { RtkOrNotebooksError } from "../../../../components/errors/RtkErrorAlert";
import AppContext from "../../../../utils/context/appContext";
import { DEFAULT_APP_PARAMS } from "../../../../utils/context/appParams.constants";
import { useProject } from "../../../ProjectPageV2/ProjectPageContainer/ProjectPageContainer";
import WipBadge from "../../../projectsV2/shared/WipBadge";
import { useGetRepositoriesProbesQuery } from "../../../repositories/repositories.api";
import type { SessionLauncherForm } from "../../sessionsV2.types";
import BuilderFrontendSelector from "./BuilderFrontendSelector";
import BuilderTypeSelector from "./BuilderTypeSelector";
import CodeRepositorySelector from "./CodeRepositorySelector";
import WipBadge from "../../../projectsV2/shared/WipBadge";

interface BuilderEnvironmentFieldsProps {
control: Control<SessionLauncherForm>;
Expand All @@ -41,6 +43,10 @@ export default function BuilderEnvironmentFields({
control,
isEdit,
}: BuilderEnvironmentFieldsProps) {
const { params } = useContext(AppContext);
const imageBuildersEnabled =
params?.IMAGE_BUILDERS_ENABLED ?? DEFAULT_APP_PARAMS.IMAGE_BUILDERS_ENABLED;

const { project } = useProject();
const repositories = project.repositories ?? [];

Expand All @@ -57,6 +63,15 @@ export default function BuilderEnvironmentFields({
[repositoriesDetails]
);

if (!imageBuildersEnabled) {
return (
<ErrorAlert dismissible={false}>
Creating a session environment from code is not currently supported by
this instance of RenkuLab. Contact an administrator to learn more.
</ErrorAlert>
);
}

const content = isLoading ? (
<p className="mb-0">
<Loader className="me-1" inline size={16} />
Expand Down Expand Up @@ -92,8 +107,8 @@ export default function BuilderEnvironmentFields({
return (
<div className={cx("d-flex", "flex-column", "gap-3")}>
<div>
<WipBadge tooltip="This is an experimental feature. Use at your own risk.">
Experimental
<WipBadge tooltip="This feature is available for you to use but still has some rough edges. We welcome your feedback as we continue to polish it.">
Early Access Feature
</WipBadge>
</div>
{!isEdit && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
* limitations under the License.
*/
import cx from "classnames";
import { useContext } from "react";
import { Control, Controller } from "react-hook-form";
import { ButtonGroup } from "reactstrap";
import AppContext from "../../../../utils/context/appContext";
import { DEFAULT_APP_PARAMS } from "../../../../utils/context/appParams.constants";
import { SessionLauncherForm } from "../../sessionsV2.types";

interface EnvironmentKindFieldProps {
Expand All @@ -26,6 +29,10 @@ interface EnvironmentKindFieldProps {
export default function EnvironmentKindField({
control,
}: EnvironmentKindFieldProps) {
const { params } = useContext(AppContext);
const imageBuildersEnabled =
params?.IMAGE_BUILDERS_ENABLED ?? DEFAULT_APP_PARAMS.IMAGE_BUILDERS_ENABLED;

return (
<Controller
control={control}
Expand Down Expand Up @@ -69,23 +76,26 @@ export default function EnvironmentKindField({
Custom Environment
</label>

<input
type="radio"
className="btn-check"
name={field.name}
autoComplete="off"
checked={field.value === "custom + build"}
id="environment-kind-builder-radio"
onChange={() => field.onChange("custom + build")}
onBlur={field.onBlur}
/>
<label
className={cx("btn", "btn-outline-primary")}
data-cy="environment-kind-builder"
htmlFor="environment-kind-builder-radio"
>
Create from code
</label>
{imageBuildersEnabled && (
<>
<input
type="radio"
className="btn-check"
name={field.name}
autoComplete="off"
checked={field.value === "custom + build"}
id="environment-kind-builder-radio"
onChange={() => field.onChange("custom + build")}
onBlur={field.onBlur}
/>
<label
className={cx("btn", "btn-outline-primary")}
htmlFor="environment-kind-builder-radio"
>
Create from code
</label>
</>
)}
</ButtonGroup>
</div>
)}
Expand Down
1 change: 1 addition & 0 deletions client/src/utils/context/appParams.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,5 @@ export const DEFAULT_APP_PARAMS: AppParams = {
UPLOAD_THRESHOLD: DEFAULT_UPLOAD_THRESHOLD,
USER_PREFERENCES_MAX_PINNED_PROJECTS:
DEFAULT_USER_PREFERENCES_MAX_PINNED_PROJECTS,
IMAGE_BUILDERS_ENABLED: false,
};
1 change: 1 addition & 0 deletions client/src/utils/context/appParams.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface AppParams {
UI_VERSION: string;
UPLOAD_THRESHOLD: UploadThresholdParams;
USER_PREFERENCES_MAX_PINNED_PROJECTS: number;
IMAGE_BUILDERS_ENABLED: boolean;
}

export type AppParamsStrings = {
Expand Down
5 changes: 5 additions & 0 deletions client/src/utils/context/appParams.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export function validatedAppParams(params: unknown): AppParams {
"PRIVACY_BANNER_ENABLED"
);
const TERMS_PAGES_ENABLED = validateBoolean(params_, "TERMS_PAGES_ENABLED");
const IMAGE_BUILDERS_ENABLED = validateBoolean(
params_,
"IMAGE_BUILDERS_ENABLED"
);

// Integer params
const USER_PREFERENCES_MAX_PINNED_PROJECTS = validateInteger(
Expand Down Expand Up @@ -108,6 +112,7 @@ export function validatedAppParams(params: unknown): AppParams {
UI_VERSION,
UPLOAD_THRESHOLD,
USER_PREFERENCES_MAX_PINNED_PROJECTS,
IMAGE_BUILDERS_ENABLED,
};
}

Expand Down
Loading