Skip to content

Commit 48e7dc5

Browse files
committed
feat: show warning if internal gitlab is referenced
1 parent 3c1d05b commit 48e7dc5

File tree

14 files changed

+778
-135
lines changed

14 files changed

+778
-135
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*!
2+
* Copyright 2025 - Swiss Data Science Center (SDSC)
3+
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
4+
* Eidgenössische Technische Hochschule Zürich (ETHZ).
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
import cx from "classnames";
20+
import { Alert } from "reactstrap";
21+
22+
interface TakeActionAlertProps {
23+
children: React.ReactNode;
24+
"data-cy"?: string;
25+
icon?: React.ReactNode;
26+
className?: string;
27+
}
28+
export default function TakeActionAlert({
29+
children,
30+
icon,
31+
...props
32+
}: TakeActionAlertProps) {
33+
return (
34+
<Alert
35+
color="take-action"
36+
isOpen
37+
data-cy={props["data-cy"]}
38+
className={cx(props.className, "overflow-y-auto")}
39+
>
40+
<div className={cx("d-flex", "gap-3")}>
41+
{icon && <div>{icon}</div>}
42+
<div className={cx("my-auto", "w-100")}>{children}</div>
43+
</div>
44+
</Alert>
45+
);
46+
}

client/src/features/ProjectPageV2/ProjectPageContent/CodeRepositories/CodeRepositoryDisplay.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ import {
4848
Row,
4949
} from "reactstrap";
5050

51+
import RepositoryGitLabWarnBadge from "~/features/legacy/RepositoryGitLabWarnBadge";
52+
5153
import { useLoginUrl } from "../../../../authentication/useLoginUrl.hook";
5254
import {
5355
ErrorAlert,
@@ -508,6 +510,11 @@ export function RepositoryItem({
508510
</>
509511
)}
510512
</Row>
513+
<Row>
514+
<Col data-cy="repo-gitlab-warning">
515+
<RepositoryGitLabWarnBadge project={project} />
516+
</Col>
517+
</Row>
511518
</ListGroupItem>
512519
{!readonly && (
513520
<RepositoryView

client/src/features/ProjectPageV2/ProjectPageHeader/ProjectPageHeader.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { ProjectImageView } from "../ProjectPageContent/ProjectInformation/Proje
2626

2727
import ProjectAutostartRedirectBanner from "./ProjectAutostartRedirectBanner";
2828
import ProjectCopyBanner from "./ProjectCopyBanner";
29+
import ProjectGitLabWarnBanner from "../../legacy/ProjectGitLabWarnBanner";
2930
import ProjectTemplateInfoBanner from "./ProjectTemplateInfoBanner";
3031

3132
interface ProjectPageHeaderProps {
@@ -75,6 +76,11 @@ export default function ProjectPageHeader({ project }: ProjectPageHeaderProps) {
7576
</Col>
7677
</Col>
7778
</Row>
79+
<Row>
80+
<Col>
81+
<ProjectGitLabWarnBanner project={project} />
82+
</Col>
83+
</Row>
7884
<Row>
7985
<Col>
8086
{project.is_template && <ProjectCopyBanner project={project} />}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*!
2+
* Copyright 2025 - Swiss Data Science Center (SDSC)
3+
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
4+
* Eidgenössische Technische Hochschule Zürich (ETHZ).
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
import cx from "classnames";
20+
import { EmojiDizzyFill } from "react-bootstrap-icons";
21+
import { Badge } from "reactstrap";
22+
23+
export default function InternalGitLabReferenceWarnBadge() {
24+
return (
25+
<Badge pill color="take-action">
26+
<EmojiDizzyFill className={cx("bi", "me-1")} />
27+
Migration needed
28+
</Badge>
29+
);
30+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*!
2+
* Copyright 2025 - Swiss Data Science Center (SDSC)
3+
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
4+
* Eidgenössische Technische Hochschule Zürich (ETHZ).
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License
17+
*/
18+
import cx from "classnames";
19+
import { EmojiDizzy } from "react-bootstrap-icons";
20+
21+
import { ExternalLink } from "~/components/ExternalLinks";
22+
import TakeActionAlert from "~/components/TakeActionAlert";
23+
import PermissionsGuard from "~/features/permissionsV2/PermissionsGuard";
24+
import type { Project } from "~/features/projectsV2/api/projectV2.api";
25+
import useProjectPermissions from "~/features/ProjectPageV2/utils/useProjectPermissions.hook";
26+
import { useGetProjectsByProjectIdSessionLaunchersQuery } from "~/features/sessionsV2/api/sessionLaunchersV2.api";
27+
import { useGetUserQueryState } from "~/features/usersV2/api/users.api";
28+
29+
import {
30+
DEFAULT_INTERNAL_GITLAB_HOSTS,
31+
doesProjectReferenceRenkulabGitLab,
32+
} from "./legacy.utils";
33+
34+
function ProjectEditorWarnBanner() {
35+
return (
36+
<>
37+
<TakeActionAlert className="p-2" icon={null}>
38+
<div className={cx("d-flex", "align-items-start", "px-4", "py-2")}>
39+
<div>
40+
<h5>
41+
<EmojiDizzy className={cx("bi", "me-3")} />
42+
</h5>
43+
</div>
44+
<div>
45+
<h5>You must take action to avoid losing access to your data.</h5>
46+
<p>
47+
<b>Resources in this project will be removed</b> unless you
48+
migrate them before the RenkuLab GitLab shut down in{" "}
49+
<b>January 2026</b>.
50+
</p>
51+
<div>
52+
<ExternalLink
53+
className="text-take-action"
54+
color="light"
55+
data-cy="help-save-work-button"
56+
role="button"
57+
showLinkIcon={true}
58+
url="https://renku.notion.site/How-to-migrate-out-of-RenkuLab-GitLab-2700df2efafc80c2b442c3ad981d86fc"
59+
>
60+
Help me save my work
61+
</ExternalLink>
62+
</div>
63+
</div>
64+
</div>
65+
</TakeActionAlert>
66+
</>
67+
);
68+
}
69+
70+
export default function ProjectGitLabWarnBanner({
71+
project,
72+
}: {
73+
project: Project;
74+
}) {
75+
const { data: currentUser } = useGetUserQueryState();
76+
const userPermissions = useProjectPermissions({ projectId: project.id });
77+
// There is no way to determine these hosts dynamically
78+
const {
79+
data: launchers,
80+
error: launchersError,
81+
isLoading: isLoadingLaunchers,
82+
} = useGetProjectsByProjectIdSessionLaunchersQuery({ projectId: project.id });
83+
if (currentUser == null) return null;
84+
if (isLoadingLaunchers || launchersError || launchers == null) return null;
85+
if (
86+
!doesProjectReferenceRenkulabGitLab(
87+
project.repositories,
88+
launchers,
89+
DEFAULT_INTERNAL_GITLAB_HOSTS
90+
)
91+
)
92+
return null;
93+
return (
94+
<PermissionsGuard
95+
disabled={null}
96+
enabled={<ProjectEditorWarnBanner />}
97+
requestedPermission="write"
98+
userPermissions={userPermissions}
99+
/>
100+
);
101+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*!
2+
* Copyright 2025 - Swiss Data Science Center (SDSC)
3+
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
4+
* Eidgenössische Technische Hochschule Zürich (ETHZ).
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
import PermissionsGuard from "~/features/permissionsV2/PermissionsGuard";
20+
import useProjectPermissions from "~/features/ProjectPageV2/utils/useProjectPermissions.hook";
21+
import type { Project } from "~/features/projectsV2/api/projectV2.api";
22+
23+
import InternalGitLabReferenceWarnBadge from "./InternalGitLabWarnBadge";
24+
import {
25+
DEFAULT_INTERNAL_GITLAB_HOSTS,
26+
doesProjectReferenceRenkulabGitLab,
27+
} from "./legacy.utils";
28+
29+
interface RepositoryGitLabWarnBadgeProps {
30+
project: Project;
31+
}
32+
33+
function RepositoryGitLabWarnBadgeForProject({
34+
project,
35+
}: RepositoryGitLabWarnBadgeProps) {
36+
const userPermissions = useProjectPermissions({
37+
projectId: project.id,
38+
});
39+
40+
return (
41+
<PermissionsGuard
42+
disabled={null}
43+
enabled={<InternalGitLabReferenceWarnBadge />}
44+
requestedPermission="write"
45+
userPermissions={userPermissions}
46+
/>
47+
);
48+
}
49+
50+
export default function RepositoryGitLabWarnBadge({
51+
project,
52+
}: RepositoryGitLabWarnBadgeProps) {
53+
if (
54+
!doesProjectReferenceRenkulabGitLab(
55+
project.repositories,
56+
[],
57+
DEFAULT_INTERNAL_GITLAB_HOSTS
58+
)
59+
)
60+
return null;
61+
62+
return <RepositoryGitLabWarnBadgeForProject project={project} />;
63+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*!
2+
* Copyright 2025 - Swiss Data Science Center (SDSC)
3+
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
4+
* Eidgenössische Technische Hochschule Zürich (ETHZ).
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
import PermissionsGuard from "~/features/permissionsV2/PermissionsGuard";
20+
import useProjectPermissions from "~/features/ProjectPageV2/utils/useProjectPermissions.hook";
21+
import { SessionLauncher } from "~/features/sessionsV2/api/sessionLaunchersV2.api";
22+
23+
import InternalGitLabReferenceWarnBadge from "./InternalGitLabWarnBadge";
24+
import {
25+
DEFAULT_INTERNAL_GITLAB_HOSTS,
26+
doesProjectReferenceRenkulabGitLab,
27+
} from "./legacy.utils";
28+
29+
type SessionEnvironmentGitLabWarningBadgeForLauncherProps = {
30+
[K in keyof SessionEnvironmentGitLabWarningBadgeProps]-?: NonNullable<
31+
SessionEnvironmentGitLabWarningBadgeProps[K]
32+
>;
33+
};
34+
function SessionEnvironmentGitLabWarningBadgeForLauncher({
35+
launcher,
36+
}: SessionEnvironmentGitLabWarningBadgeForLauncherProps) {
37+
const userPermissions = useProjectPermissions({
38+
projectId: launcher.project_id,
39+
});
40+
41+
return (
42+
<PermissionsGuard
43+
disabled={null}
44+
enabled={<InternalGitLabReferenceWarnBadge />}
45+
requestedPermission="write"
46+
userPermissions={userPermissions}
47+
/>
48+
);
49+
}
50+
51+
interface SessionEnvironmentGitLabWarningBadgeProps {
52+
launcher: SessionLauncher | null | undefined;
53+
}
54+
55+
export default function SessionEnvironmentGitLabWarningBadge({
56+
launcher,
57+
}: SessionEnvironmentGitLabWarningBadgeProps) {
58+
if (!launcher) return null;
59+
if (
60+
!doesProjectReferenceRenkulabGitLab(
61+
undefined,
62+
[launcher],
63+
DEFAULT_INTERNAL_GITLAB_HOSTS
64+
)
65+
)
66+
return null;
67+
return (
68+
<SessionEnvironmentGitLabWarningBadgeForLauncher launcher={launcher} />
69+
);
70+
}

0 commit comments

Comments
 (0)