You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kie.apache.org by ti...@apache.org on 2025/05/29 18:01:42 UTC

(incubator-kie-tools) branch main updated: kie-issues#11: GitLab support on KIE Sandbox (#3132)

This is an automated email from the ASF dual-hosted git repository.

tiagobento pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git


The following commit(s) were added to refs/heads/main by this push:
     new 0351d2e094e kie-issues#11: GitLab support on KIE Sandbox (#3132)
0351d2e094e is described below

commit 0351d2e094e3d1df60051d2acfdb713f850a88e6
Author: Adarsh vk <33...@users.noreply.github.com>
AuthorDate: Thu May 29 23:31:39 2025 +0530

    kie-issues#11: GitLab support on KIE Sandbox (#3132)
---
 packages/cors-proxy-api/src/index.ts               |   1 +
 packages/cors-proxy/src/proxy/ExpressCorsProxy.ts  |   5 +
 packages/i18n-common-dictionary/src/names.ts       |   1 +
 packages/online-editor/build/defaultEnvJson.ts     |   3 +-
 .../online-editor/src/accounts/AccountsContext.tsx |  21 ++
 .../online-editor/src/accounts/AccountsIcon.tsx    |  29 +++
 .../src/accounts/git/ConnectToGitSection.tsx       |  82 +++++++-
 .../src/authProviders/AuthProvidersApi.ts          |  13 +-
 .../src/authProviders/AuthProvidersGallery.tsx     |  10 +
 .../src/authSessions/AuthSessionsContext.tsx       |  21 +-
 packages/online-editor/src/bitbucket/Hooks.tsx     |   6 +
 .../GitIntegration/CreateGistOrSnippetModal.tsx    |  55 ++++-
 .../GitIntegration/CreateGitRepositoryModal.tsx    |  50 ++++-
 .../GitIntegration/GitIntegrationAlerts.tsx        |  20 +-
 .../GitIntegrationContextProvider.tsx              |  73 ++++++-
 .../GitIntegration/LoadOrganizationsSelect.tsx     | 103 +++++++---
 .../src/editor/Toolbar/NewFileDropdownMenu.tsx     |  13 +-
 .../src/editor/Toolbar/Share/GitDropdownGroup.tsx  |   8 +-
 .../src/editor/Toolbar/SyncDropdownMenu.tsx        |   6 +
 .../src/editor/Toolbar/Workspace/Hooks.tsx         |   2 +
 packages/online-editor/src/github/Hooks.tsx        |   8 +
 packages/online-editor/src/gitlab/GitlabClient.ts  | 222 +++++++++++++++++++++
 .../online-editor/src/gitlab/ParseGitLabUrl.ts     | 181 +++++++++++++++++
 .../online-editor/src/gitlab/useGitlabClient.ts    |  81 ++++++++
 packages/online-editor/src/i18n/locales/de.ts      |  59 ++++++
 packages/online-editor/src/i18n/locales/en.ts      |  59 ++++++
 .../importFromUrl/AdvancedImportModalContent.tsx   |  18 +-
 .../importFromUrl/ImportFromUrlHomePageCard.tsx    |  40 +++-
 .../importFromUrl/ImportSingleFileFromUrlForm.tsx  |   2 +-
 .../src/importFromUrl/ImportableUrlHooks.tsx       | 129 ++++++++++--
 .../src/importFromUrl/NewWorkspaceFromUrlPage.tsx  |  38 +++-
 .../src/importFromUrl/fetchSingleFileContent.ts    |  38 +++-
 packages/online-editor/src/navigation/Routes.ts    |   2 +
 .../src/workspace/components/WorkspaceLabel.tsx    |  13 ++
 .../src/context/WorkspacesContext.tsx              |  28 ++-
 .../src/context/WorkspacesContextProvider.tsx      |  46 ++++-
 .../workspaces-git-fs/src/services/GitService.tsx  |  31 ++-
 .../src/services/WorkspaceDescriptorService.tsx    |  49 ++++-
 .../src/services/WorkspaceService.tsx              |   2 +
 .../src/worker/WorkspacesWorkerApiImpl.ts          |  53 ++++-
 .../src/worker/api/WorkspaceDescriptor.tsx         |   1 +
 .../src/worker/api/WorkspaceOrigin.tsx             |  37 +++-
 .../src/worker/api/WorkspacesWorkerGitApi.ts       |  28 ++-
 43 files changed, 1558 insertions(+), 129 deletions(-)

diff --git a/packages/cors-proxy-api/src/index.ts b/packages/cors-proxy-api/src/index.ts
index ebcfb9288f5..b623f62e559 100644
--- a/packages/cors-proxy-api/src/index.ts
+++ b/packages/cors-proxy-api/src/index.ts
@@ -20,6 +20,7 @@
 export enum CorsProxyHeaderKeys {
   TARGET_URL = "target-url",
   INSECURELY_DISABLE_TLS_CERTIFICATE_VALIDATION = "insecurely-disable-tls-certificate-validation",
+  DISABLE_ENCODING = "disable-encoding",
 }
 
 export type CorsConfig = {
diff --git a/packages/cors-proxy/src/proxy/ExpressCorsProxy.ts b/packages/cors-proxy/src/proxy/ExpressCorsProxy.ts
index 55627402fe8..b8a78f313c5 100644
--- a/packages/cors-proxy/src/proxy/ExpressCorsProxy.ts
+++ b/packages/cors-proxy/src/proxy/ExpressCorsProxy.ts
@@ -29,6 +29,7 @@ const BANNED_PROXY_HEADERS = [
   "host",
   CorsProxyHeaderKeys.TARGET_URL,
   CorsProxyHeaderKeys.INSECURELY_DISABLE_TLS_CERTIFICATE_VALIDATION,
+  CorsProxyHeaderKeys.DISABLE_ENCODING,
 ];
 
 export class ExpressCorsProxy implements CorsProxy<Request, Response> {
@@ -73,6 +74,10 @@ export class ExpressCorsProxy implements CorsProxy<Request, Response> {
       if (req.headers[CorsProxyHeaderKeys.INSECURELY_DISABLE_TLS_CERTIFICATE_VALIDATION] === "true") {
         outHeaders["accept-encoding"] = "identity";
       }
+      // Force uncompressed response if encoding is disabled via header
+      if (req.headers[CorsProxyHeaderKeys.DISABLE_ENCODING] === "true") {
+        outHeaders["accept-encoding"] = "identity";
+      }
 
       this.logger.log("Proxying to: ", info.proxyUrl.toString());
       this.logger.debug("Proxy Method: ", req.method);
diff --git a/packages/i18n-common-dictionary/src/names.ts b/packages/i18n-common-dictionary/src/names.ts
index 43b4e121a5f..0f95031d44b 100644
--- a/packages/i18n-common-dictionary/src/names.ts
+++ b/packages/i18n-common-dictionary/src/names.ts
@@ -36,6 +36,7 @@ export const names = {
   dropbox: "Dropbox",
   git: "Git",
   github: "GitHub",
+  gitlab: "GitLab",
   kogito: "Kogito",
   linux: "Linux",
   macos: "macOS",
diff --git a/packages/online-editor/build/defaultEnvJson.ts b/packages/online-editor/build/defaultEnvJson.ts
index 46bd281196c..5608b7d9c3d 100644
--- a/packages/online-editor/build/defaultEnvJson.ts
+++ b/packages/online-editor/build/defaultEnvJson.ts
@@ -74,9 +74,10 @@ export const defaultEnvJson: EnvJson = {
       supportedGitRemoteDomains: ["gitlab.com"],
       type: AuthProviderType.gitlab,
       name: "GitLab",
-      enabled: false,
+      enabled: true,
       iconPath: routes.static.images.gitlabLogo.path({}),
       group: AuthProviderGroup.GIT,
+      disableEncoding: true,
     },
     {
       id: "bitbucket_dot_org",
diff --git a/packages/online-editor/src/accounts/AccountsContext.tsx b/packages/online-editor/src/accounts/AccountsContext.tsx
index e025095c261..57ba3b132b5 100644
--- a/packages/online-editor/src/accounts/AccountsContext.tsx
+++ b/packages/online-editor/src/accounts/AccountsContext.tsx
@@ -36,6 +36,7 @@ export enum AccountsSection {
   CONNECT_TO_AN_ACCOUNT = "CONNECT_TO_AN_ACCOUNT",
   CONNECT_TO_GITHUB = "CONNECT_TO_GITHUB",
   CONNECT_TO_BITBUCKET = "CONNECT_TO_BITBUCKET",
+  CONNECT_TO_GITLAB = "CONNECT_TO_GITLAB",
   CONNECT_TO_OPENSHIFT = "CONNECT_TO_OPENSHIFT",
   CONNECT_TO_KUBERNETES = "CONNECT_TO_KUBERNETES",
 }
@@ -67,6 +68,12 @@ export type AccountsState =
       backActionKind: AccountsDispatchActionKind.SELECT_AUTH_PROVIDER | AccountsDispatchActionKind.GO_HOME;
       onNewAuthSession?: (newAuthSession: AuthSession) => any;
     }
+  | {
+      section: AccountsSection.CONNECT_TO_GITLAB;
+      selectedAuthProvider: GitAuthProvider;
+      backActionKind: AccountsDispatchActionKind.SELECT_AUTH_PROVIDER | AccountsDispatchActionKind.GO_HOME;
+      onNewAuthSession?: (newAuthSession: AuthSession) => any;
+    }
   | {
       section: AccountsSection.CONNECT_TO_OPENSHIFT;
       selectedAuthProvider: OpenShiftAuthProvider;
@@ -88,6 +95,7 @@ export enum AccountsDispatchActionKind {
   SELECT_AUTH_PROVIDER = "SELECT_AUTH_PROVIDER",
   SETUP_GITHUB_AUTH = "SETUP_GITHUB_AUTH",
   SETUP_BITBUCKET_AUTH = "SETUP_BITBUCKET_AUTH",
+  SETUP_GITLAB_AUTH = "SETUP_GITLAB_AUTH",
   SETUP_OPENSHIFT_AUTH = "SETUP_OPENSHIFT_AUTH",
   SETUP_KUBERNETES_AUTH = "SETUP_KUBERNETES_AUTH",
 }
@@ -116,6 +124,12 @@ export type AccountsDispatchAction =
       backActionKind: AccountsDispatchActionKind.SELECT_AUTH_PROVIDER | AccountsDispatchActionKind.GO_HOME;
       onNewAuthSession?: (newAuthSession: AuthSession) => any;
     }
+  | {
+      kind: AccountsDispatchActionKind.SETUP_GITLAB_AUTH;
+      selectedAuthProvider: GitAuthProvider;
+      backActionKind: AccountsDispatchActionKind.SELECT_AUTH_PROVIDER | AccountsDispatchActionKind.GO_HOME;
+      onNewAuthSession?: (newAuthSession: AuthSession) => any;
+    }
   | {
       kind: AccountsDispatchActionKind.SETUP_OPENSHIFT_AUTH;
       selectedAuthProvider: OpenShiftAuthProvider;
@@ -174,6 +188,13 @@ export function AccountsContextProvider(props: React.PropsWithChildren<{}>) {
             onNewAuthSession: action.onNewAuthSession,
             backActionKind: action.backActionKind,
           };
+        case AccountsDispatchActionKind.SETUP_GITLAB_AUTH:
+          return {
+            section: AccountsSection.CONNECT_TO_GITLAB,
+            selectedAuthProvider: action.selectedAuthProvider,
+            onNewAuthSession: action.onNewAuthSession,
+            backActionKind: action.backActionKind,
+          };
         case AccountsDispatchActionKind.SETUP_OPENSHIFT_AUTH:
           return {
             section: AccountsSection.CONNECT_TO_OPENSHIFT,
diff --git a/packages/online-editor/src/accounts/AccountsIcon.tsx b/packages/online-editor/src/accounts/AccountsIcon.tsx
index dfdd7eccfc9..579d2fc2bc8 100644
--- a/packages/online-editor/src/accounts/AccountsIcon.tsx
+++ b/packages/online-editor/src/accounts/AccountsIcon.tsx
@@ -168,6 +168,32 @@ export function AccountsIcon() {
                   </Flex>
                 </>
               )}
+              {accounts.section === AccountsSection.CONNECT_TO_GITLAB && (
+                <>
+                  <Flex justifyContent={{ default: "justifyContentSpaceBetween" }}>
+                    <FlexItem>
+                      <Flex
+                        justifyContent={{ default: "justifyContentFlexStart" }}
+                        spaceItems={{ default: "spaceItemsSm" }}
+                      >
+                        <TextContent>
+                          <Text component={TextVariants.h2}>
+                            {`Connect to`}
+                            &nbsp;
+                            {accounts.selectedAuthProvider.name}
+                          </Text>
+                        </TextContent>
+                        <TextContent>
+                          <Text component={TextVariants.small}>
+                            <i>{accounts.selectedAuthProvider.domain}</i>
+                          </Text>
+                        </TextContent>
+                      </Flex>
+                    </FlexItem>
+                    <AuthProviderIcon authProvider={accounts.selectedAuthProvider} size={"sm"} />
+                  </Flex>
+                </>
+              )}
               {accounts.section === AccountsSection.CONNECT_TO_OPENSHIFT && (
                 <>
                   <TextContent>
@@ -234,6 +260,9 @@ export function AccountsIcon() {
               {accounts.section === AccountsSection.CONNECT_TO_BITBUCKET && (
                 <ConnectToGitSection authProvider={accounts.selectedAuthProvider} />
               )}
+              {accounts.section === AccountsSection.CONNECT_TO_GITLAB && (
+                <ConnectToGitSection authProvider={accounts.selectedAuthProvider} />
+              )}
               {accounts.section === AccountsSection.CONNECT_TO_OPENSHIFT && <ConnectToOpenShiftSection />}
               {accounts.section === AccountsSection.CONNECT_TO_KUBERNETES && <ConnectToKubernetesSection />}
             </>
diff --git a/packages/online-editor/src/accounts/git/ConnectToGitSection.tsx b/packages/online-editor/src/accounts/git/ConnectToGitSection.tsx
index 57bbdfe100c..d7749b6dfec 100644
--- a/packages/online-editor/src/accounts/git/ConnectToGitSection.tsx
+++ b/packages/online-editor/src/accounts/git/ConnectToGitSection.tsx
@@ -45,14 +45,18 @@ import {
 import { switchExpression } from "@kie-tools-core/switch-expression-ts";
 import { AuthOptionsType, getBitbucketClient } from "../../bitbucket/Hooks";
 import { useEnv } from "../../env/hooks/EnvContext";
+import { getGitlabClient } from "../../gitlab/useGitlabClient";
 import { HelperText, HelperTextItem } from "@patternfly/react-core/dist/js/components/HelperText";
 
 export const GITHUB_OAUTH_TOKEN_SIZE = 40;
 export const BITBUCKET_OAUTH_TOKEN_SIZE = 40;
+export const GITLAB_OAUTH_TOKEN_SIZE = 40;
 
 export const GITHUB_TOKENS_HOW_TO_URL =
   "https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token";
 export const BITBUCKET_TOKENS_HOW_TO_URL = "https://support.atlassian.com/bitbucket-cloud/docs/create-an-app-password/";
+export const GITLAB_TOKENS_HOW_TO_URL =
+  "https://docs.gitlab.com/user/profile/personal_access_tokens/#create-a-personal-access-token";
 
 export const GITHUB_OAUTH_SCOPES = ["repo", "gist"];
 export const BITBUCKET_OAUTH_SCOPES = [
@@ -64,6 +68,8 @@ export const BITBUCKET_OAUTH_SCOPES = [
   "snippet:write",
 ];
 
+export const GITLAB_OAUTH_SCOPES = ["api", "read_user", "read_repository", "write_repository"];
+
 export type AuthenticatedUserResponse = {
   headers: {
     scopes: string[];
@@ -119,14 +125,25 @@ export function ConnectToGitSection(props: { authProvider: GitAuthProvider }) {
                   tokenInput,
                   props.authProvider.domain,
                   env.KIE_SANDBOX_CORS_PROXY_URL,
-                  props.authProvider.insecurelyDisableTlsCertificateValidation
+                  props.authProvider.insecurelyDisableTlsCertificateValidation,
+                  props.authProvider.disableEncoding
                 ),
               github: () =>
                 fetchAuthenticatedGitHubUser(
                   tokenInput,
                   props.authProvider.domain,
                   env.KIE_SANDBOX_CORS_PROXY_URL,
-                  props.authProvider.insecurelyDisableTlsCertificateValidation
+                  props.authProvider.insecurelyDisableTlsCertificateValidation,
+                  props.authProvider.disableEncoding
+                ),
+              gitlab: () =>
+                fetchAuthenticatedGitlabUser(
+                  env.KIE_SANDBOX_APP_NAME,
+                  tokenInput,
+                  props.authProvider.domain,
+                  env.KIE_SANDBOX_CORS_PROXY_URL,
+                  props.authProvider.insecurelyDisableTlsCertificateValidation,
+                  props.authProvider.disableEncoding
                 ),
             })
           )
@@ -137,6 +154,7 @@ export function ConnectToGitSection(props: { authProvider: GitAuthProvider }) {
             const requiredScopes = switchExpression(authProviderType, {
               bitbucket: BITBUCKET_OAUTH_SCOPES,
               github: GITHUB_OAUTH_SCOPES,
+              gitlab: GITLAB_OAUTH_SCOPES,
             });
             if (!response.headers.scopes.some((it) => requiredScopes.includes(it))) {
               setNewAuthSession({
@@ -176,6 +194,7 @@ export function ConnectToGitSection(props: { authProvider: GitAuthProvider }) {
         props.authProvider.type,
         props.authProvider.domain,
         props.authProvider.insecurelyDisableTlsCertificateValidation,
+        props.authProvider.disableEncoding,
         props.authProvider.id,
         tokenInput,
         success,
@@ -230,7 +249,8 @@ export function ConnectToGitSection(props: { authProvider: GitAuthProvider }) {
   const successPrimaryAction = useMemo(() => {
     if (
       (accounts.section !== AccountsSection.CONNECT_TO_GITHUB &&
-        accounts.section !== AccountsSection.CONNECT_TO_BITBUCKET) ||
+        accounts.section !== AccountsSection.CONNECT_TO_BITBUCKET &&
+        accounts.section !== AccountsSection.CONNECT_TO_GITLAB) ||
       !newAuthSession.data
     ) {
       return;
@@ -331,6 +351,7 @@ export function ConnectToGitSection(props: { authProvider: GitAuthProvider }) {
               href={switchExpression(props.authProvider.type, {
                 bitbucket: generateNewBitbucketTokenUrl(props.authProvider.domain),
                 github: generateNewGitHubTokenUrl(props.authProvider.domain),
+                gitlab: generateNewGitlabTokenUrl(props.authProvider.domain),
               })}
               target={"_blank"}
               rel={"noopener"}
@@ -351,6 +372,7 @@ export function ConnectToGitSection(props: { authProvider: GitAuthProvider }) {
                 href={switchExpression(props.authProvider.type, {
                   bitbucket: BITBUCKET_TOKENS_HOW_TO_URL,
                   github: GITHUB_TOKENS_HOW_TO_URL,
+                  gitlab: GITLAB_TOKENS_HOW_TO_URL,
                 })}
                 target={"_blank"}
                 rel={"noopener"}
@@ -370,6 +392,7 @@ export function ConnectToGitSection(props: { authProvider: GitAuthProvider }) {
     return switchExpression(props.authProvider.type, {
       bitbucket: BITBUCKET_OAUTH_TOKEN_SIZE,
       github: GITHUB_OAUTH_TOKEN_SIZE,
+      gitlab: GITLAB_OAUTH_TOKEN_SIZE,
       default: -1,
     });
   }
@@ -391,6 +414,8 @@ export const generateNewBitbucketTokenUrl = (domain: string) => {
 export const generateNewGitHubTokenUrl = (domain: string) => {
   return `https://${domain}/settings/tokens`;
 };
+export const generateNewGitlabTokenUrl = (domain: string): string =>
+  `https://${domain}/-/user_settings/personal_access_tokens`;
 
 function delay(ms: number) {
   return new Promise((res) => setTimeout(res, ms));
@@ -404,9 +429,16 @@ export const fetchAuthenticatedGitHubUser = async (
   githubToken: string,
   domain?: string,
   proxyUrl?: string,
-  insecurelyDisableTlsCertificateValidation?: boolean
+  insecurelyDisableTlsCertificateValidation?: boolean,
+  disableEncoding?: boolean
 ) => {
-  const octokit = getOctokitClient({ githubToken, domain, proxyUrl, insecurelyDisableTlsCertificateValidation });
+  const octokit = getOctokitClient({
+    githubToken,
+    domain,
+    proxyUrl,
+    insecurelyDisableTlsCertificateValidation,
+    disableEncoding,
+  });
   const response = await octokit.users.getAuthenticated();
   return {
     data: {
@@ -425,7 +457,8 @@ export const fetchAuthenticatedBitbucketUser = async (
   bitbucketToken: string,
   domain?: string,
   proxyUrl?: string,
-  insecurelyDisableTlsCertificateValidation?: boolean
+  insecurelyDisableTlsCertificateValidation?: boolean,
+  disableEncoding?: boolean
 ) => {
   const bitbucketClient = getBitbucketClient({
     appName,
@@ -437,6 +470,7 @@ export const fetchAuthenticatedBitbucketUser = async (
     },
     proxyUrl,
     insecurelyDisableTlsCertificateValidation,
+    disableEncoding,
   });
 
   const response = await bitbucketClient.getAuthedUser();
@@ -456,3 +490,39 @@ export const fetchAuthenticatedBitbucketUser = async (
     headers: { scopes: response.headers.get("x-oauth-scopes")?.split(", ") ?? [] },
   };
 };
+
+export const fetchAuthenticatedGitlabUser = async (
+  appName: string,
+  gitlabToken: string,
+  domain?: string,
+  proxyUrl?: string,
+  insecurelyDisableTlsCertificateValidation?: boolean,
+  disableEncoding?: boolean
+) => {
+  const gitlabClient = getGitlabClient({
+    appName,
+    domain,
+    token: gitlabToken,
+    proxyUrl,
+    insecurelyDisableTlsCertificateValidation,
+    disableEncoding,
+  });
+
+  const response = await gitlabClient.getAuthedUser();
+
+  if (!response.ok) {
+    const message = await response.text();
+    throw new Error(`While authenticating : ${response.status} ${response.statusText} ${message}`);
+  }
+  const jsonResponse = await response.json();
+
+  return {
+    data: {
+      name: jsonResponse?.name,
+      login: jsonResponse?.username,
+      email: jsonResponse?.email,
+    },
+    // GitLab does not expose PAT scopes in the response
+    headers: { scopes: [] },
+  };
+};
diff --git a/packages/online-editor/src/authProviders/AuthProvidersApi.ts b/packages/online-editor/src/authProviders/AuthProvidersApi.ts
index b661b639bbf..072991507f5 100644
--- a/packages/online-editor/src/authProviders/AuthProvidersApi.ts
+++ b/packages/online-editor/src/authProviders/AuthProvidersApi.ts
@@ -31,7 +31,11 @@ export enum AuthProviderType {
 }
 
 const gitAuthProviderKeys = [AuthProviderType.bitbucket, AuthProviderType.github, AuthProviderType.gitlab] as const;
-const supportedGitAuthProvidersKeys = [AuthProviderType.bitbucket, AuthProviderType.github] as const;
+const supportedGitAuthProvidersKeys = [
+  AuthProviderType.bitbucket,
+  AuthProviderType.github,
+  AuthProviderType.gitlab,
+] as const;
 export type SupportedGitAuthProviders = (typeof supportedGitAuthProvidersKeys)[number];
 export const isSupportedGitAuthProviderType = (
   maybeSupportedTypeKey: AuthProviderType | undefined
@@ -78,11 +82,16 @@ export type GitAuthProvider = {
   supportedGitRemoteDomains: string[];
   group: AuthProviderGroup.GIT;
   insecurelyDisableTlsCertificateValidation?: boolean;
+  disableEncoding?: boolean;
 };
 
 export type AuthProvider = OpenShiftAuthProvider | KubernetesAuthProvider | GitAuthProvider;
 
-const gistEnabledTypeConfigKeys = [AuthProviderType.github, AuthProviderType.bitbucket] as const;
+const gistEnabledTypeConfigKeys = [
+  AuthProviderType.github,
+  AuthProviderType.bitbucket,
+  AuthProviderType.gitlab,
+] as const;
 export type GistEnabledAuthProviderType = (typeof gistEnabledTypeConfigKeys)[number];
 
 export const isGistEnabledAuthProviderType = (
diff --git a/packages/online-editor/src/authProviders/AuthProvidersGallery.tsx b/packages/online-editor/src/authProviders/AuthProvidersGallery.tsx
index 1e03177d6fb..623b08f2d06 100644
--- a/packages/online-editor/src/authProviders/AuthProvidersGallery.tsx
+++ b/packages/online-editor/src/authProviders/AuthProvidersGallery.tsx
@@ -102,6 +102,16 @@ export function AuthProvidersGallery(props: {
                               ? accounts.onNewAuthSession
                               : undefined,
                         });
+                      } else if (authProvider.enabled && authProvider.type === "gitlab") {
+                        accountsDispatch({
+                          kind: AccountsDispatchActionKind.SETUP_GITLAB_AUTH,
+                          selectedAuthProvider: authProvider,
+                          backActionKind: props.backActionKind,
+                          onNewAuthSession:
+                            accounts.section === AccountsSection.CONNECT_TO_AN_ACCOUNT
+                              ? accounts.onNewAuthSession
+                              : undefined,
+                        });
                       } else if (authProvider.enabled && authProvider.type === "openshift") {
                         accountsDispatch({
                           kind: AccountsDispatchActionKind.SETUP_OPENSHIFT_AUTH,
diff --git a/packages/online-editor/src/authSessions/AuthSessionsContext.tsx b/packages/online-editor/src/authSessions/AuthSessionsContext.tsx
index e3e3758d55b..c6c137f688d 100644
--- a/packages/online-editor/src/authSessions/AuthSessionsContext.tsx
+++ b/packages/online-editor/src/authSessions/AuthSessionsContext.tsx
@@ -23,7 +23,11 @@ import { useCancelableEffect } from "@kie-tools-core/react-hooks/dist/useCancela
 import { decoder, encoder } from "@kie-tools-core/workspaces-git-fs/dist/encoderdecoder/EncoderDecoder";
 import { LfsStorageFile } from "@kie-tools-core/workspaces-git-fs/dist/lfs/LfsStorageService";
 import { useAuthProviders } from "../authProviders/AuthProvidersContext";
-import { fetchAuthenticatedBitbucketUser, fetchAuthenticatedGitHubUser } from "../accounts/git/ConnectToGitSection";
+import {
+  fetchAuthenticatedBitbucketUser,
+  fetchAuthenticatedGitHubUser,
+  fetchAuthenticatedGitlabUser,
+} from "../accounts/git/ConnectToGitSection";
 import {
   AuthSession,
   AuthSessionStatus,
@@ -166,14 +170,25 @@ export function AuthSessionsContextProvider(props: PropsWithChildren<{}>) {
                         authSession.token,
                         authProvider?.domain,
                         env.KIE_SANDBOX_CORS_PROXY_URL,
-                        authProvider?.insecurelyDisableTlsCertificateValidation
+                        authProvider?.insecurelyDisableTlsCertificateValidation,
+                        authProvider?.disableEncoding
                       ),
                     github: () =>
                       fetchAuthenticatedGitHubUser(
                         authSession.token,
                         authProvider?.domain,
                         env.KIE_SANDBOX_CORS_PROXY_URL,
-                        authProvider?.insecurelyDisableTlsCertificateValidation
+                        authProvider?.insecurelyDisableTlsCertificateValidation,
+                        authProvider?.disableEncoding
+                      ),
+                    gitlab: () =>
+                      fetchAuthenticatedGitlabUser(
+                        env.KIE_SANDBOX_APP_NAME,
+                        authSession.token,
+                        authProvider?.domain,
+                        env.KIE_SANDBOX_CORS_PROXY_URL,
+                        authProvider?.insecurelyDisableTlsCertificateValidation,
+                        authProvider?.disableEncoding
                       ),
                   });
                   await fetchUser();
diff --git a/packages/online-editor/src/bitbucket/Hooks.tsx b/packages/online-editor/src/bitbucket/Hooks.tsx
index fc252de5ea6..f812d20fcdf 100644
--- a/packages/online-editor/src/bitbucket/Hooks.tsx
+++ b/packages/online-editor/src/bitbucket/Hooks.tsx
@@ -227,6 +227,7 @@ export function getBitbucketClient(args: {
   domain?: string;
   proxyUrl?: string;
   insecurelyDisableTlsCertificateValidation?: boolean;
+  disableEncoding?: boolean;
 }) {
   return new BitbucketClient({
     appName: args.appName,
@@ -241,6 +242,10 @@ export function getBitbucketClient(args: {
             ).toString(),
           }
         : {}),
+      // If disableEncoding is true, force proxy/server to skip compression
+      ...(args.disableEncoding
+        ? { [CorsProxyHeaderKeys.DISABLE_ENCODING]: Boolean(args.disableEncoding).toString() }
+        : {}),
     },
   });
 }
@@ -269,6 +274,7 @@ export function useBitbucketClient(authSession: AuthSession | undefined): Bitbuc
       },
       proxyUrl: env.KIE_SANDBOX_CORS_PROXY_URL,
       insecurelyDisableTlsCertificateValidation: authProvider.insecurelyDisableTlsCertificateValidation,
+      disableEncoding: authProvider.disableEncoding,
     });
   }, [authProviders, authSession, env.KIE_SANDBOX_APP_NAME, env.KIE_SANDBOX_CORS_PROXY_URL]);
 }
diff --git a/packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGistOrSnippetModal.tsx b/packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGistOrSnippetModal.tsx
index b557f539a95..3302ecd6bd9 100644
--- a/packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGistOrSnippetModal.tsx
+++ b/packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGistOrSnippetModal.tsx
@@ -27,6 +27,7 @@ import { Radio } from "@patternfly/react-core/dist/js/components/Radio";
 
 import { UsersIcon } from "@patternfly/react-icons/dist/js/icons/users-icon";
 import { LockIcon } from "@patternfly/react-icons/dist/js/icons/lock-icon";
+import { GitlabIcon } from "@patternfly/react-icons/dist/js/icons/gitlab-icon";
 
 import { Button } from "@patternfly/react-core/dist/js/components/Button";
 import { GIST_ORIGIN_REMOTE_NAME } from "@kie-tools-core/workspaces-git-fs/dist/constants/GitConstants";
@@ -49,8 +50,8 @@ import { useOnlineI18n } from "../../../i18n";
 import { LoadOrganizationsSelect, SelectOptionObjectType } from "./LoadOrganizationsSelect";
 import { useGitIntegration } from "./GitIntegrationContextProvider";
 import { useEnv } from "../../../env/hooks/EnvContext";
+import { useGitlabClient } from "../../../gitlab/useGitlabClient";
 import { HelperText, HelperTextItem } from "@patternfly/react-core/dist/js/components/HelperText";
-
 export interface CreateGistOrSnippetResponse {
   cloneUrl: string;
   htmlUrl: string;
@@ -68,6 +69,7 @@ export const CreateGistOrSnippetModal = (props: {
   const authProvider = useAuthProvider(authSession);
   const bitbucketClient = useBitbucketClient(authSession);
   const gitHubClient = useGitHubClient(authSession);
+  const gitlabClient = useGitlabClient(authSession);
 
   const [isPrivate, setPrivate] = useState(false);
   const [error, setError] = useState<string | undefined>(undefined);
@@ -107,17 +109,17 @@ If you are, it means that creating this Gist failed and it can safely be deleted
     if (selectedOrganization?.kind !== "organization") {
       throw new Error("No workspace was selected for Bitbucket Snippet.");
     }
+    const bitbucketWorkspace = (selectedOrganization as SelectOptionObjectType<"organization">).selectedOption;
     const response = await bitbucketClient.createSnippet({
-      workspace: selectedOrganization.value,
+      workspace: bitbucketWorkspace.name,
       title: props.workspace.name ?? `${env.KIE_SANDBOX_APP_NAME} Snippet`,
       files: {
         "README.md": {
           content: `
-This Snippet was created from ${env.KIE_SANDBOX_APP_NAME}.
+          This Snippet was created from ${env.KIE_SANDBOX_APP_NAME}.
 
-This file is temporary and you should not be seeing it.
-If you are, it means that creating this Snippet failed and it can safely be deleted.
-`,
+          This file is temporary and you should not be seeing it.
+          If you are, it means that creating this Snippet failed and it can safely be deleted.`,
         },
       },
       isPrivate,
@@ -136,6 +138,35 @@ If you are, it means that creating this Snippet failed and it can safely be dele
     return { cloneUrl, htmlUrl: json.links.html.href };
   }, [bitbucketClient, env.KIE_SANDBOX_APP_NAME, isPrivate, props.workspace.name, selectedOrganization]);
 
+  const createGitlabSnippet: () => Promise<CreateGistOrSnippetResponse> = useCallback(async () => {
+    const gitlabGroupOrProject = (selectedOrganization as SelectOptionObjectType<"organization">).selectedOption;
+    const snippetResponse = await gitlabClient.createSnippet({
+      title: props?.workspace?.name ?? `${env.KIE_SANDBOX_APP_NAME} Snippet`,
+      visibility: isPrivate ? "private" : "public",
+      files: [
+        {
+          file_path: "README.md",
+          content: `
+          This Snippet was created from ${env.KIE_SANDBOX_APP_NAME}.
+
+          This file is temporary and you should not be seeing it.
+          If you are, it means that creating this Snippet failed and it can safely be deleted.`,
+        },
+      ],
+      id: gitlabGroupOrProject.value,
+    });
+    if (!(snippetResponse.status === 201)) {
+      throw new Error(
+        `Gitlab snippet creation request failed with: ${snippetResponse.status} ${snippetResponse.statusText}`
+      );
+    }
+    const repo = await snippetResponse.json();
+    if (!repo?.http_url_to_repo || !repo?.web_url) {
+      throw new Error("Unexpected contents of the Gitlab snippet creation response.");
+    }
+    return { cloneUrl: repo?.http_url_to_repo, htmlUrl: repo?.web_url };
+  }, [gitlabClient, env.KIE_SANDBOX_APP_NAME, isPrivate, props.workspace.name, selectedOrganization]);
+
   const createGistOrSnippet = useCallback(async () => {
     try {
       if (!authInfo || !isGistEnabledAuthProviderType(authProvider?.type)) {
@@ -147,11 +178,14 @@ If you are, it means that creating this Snippet failed and it can safely be dele
       const insecurelyDisableTlsCertificateValidation =
         authProvider?.group === AuthProviderGroup.GIT && authProvider.insecurelyDisableTlsCertificateValidation;
 
+      const disableEncoding = authProvider?.group === AuthProviderGroup.GIT && authProvider.disableEncoding;
+
       const createGistOrSnippetCommand: () => Promise<CreateGistOrSnippetResponse> = switchExpression(
         gistEnabledAuthProvider,
         {
           github: createGitHubGist,
           bitbucket: createBitbucketSnippet,
+          gitlab: createGitlabSnippet,
         }
       );
       const gistOrSnippet = await createGistOrSnippetCommand();
@@ -161,6 +195,7 @@ If you are, it means that creating this Snippet failed and it can safely be dele
           url: new URL(gistOrSnippet.cloneUrl).toString(),
           authInfo,
           insecurelyDisableTlsCertificateValidation,
+          disableEncoding,
         })
       )
         .find((serverRef) => serverRef.ref === "HEAD")!
@@ -171,15 +206,18 @@ If you are, it means that creating this Snippet failed and it can safely be dele
         remoteUrl: URL;
         branch: string;
         insecurelyDisableTlsCertificateValidation?: boolean;
+        disableEncoding?: boolean;
       }) => Promise<void> = switchExpression(gistEnabledAuthProvider, {
         github: workspaces.initGistOnWorkspace,
         bitbucket: workspaces.initSnippetOnWorkspace,
+        gitlab: workspaces.initGilabSnippetOnWorkspace,
       });
       await initWorkspaceCommand({
         workspaceId: props.workspace.workspaceId,
         remoteUrl: new URL(gistOrSnippet.cloneUrl),
         branch: gistOrSnippetDefaultBranch,
         insecurelyDisableTlsCertificateValidation,
+        disableEncoding,
       });
 
       await workspaces.addRemote({
@@ -207,11 +245,13 @@ If you are, it means that creating this Snippet failed and it can safely be dele
         force: true,
         authInfo,
         insecurelyDisableTlsCertificateValidation,
+        disableEncoding,
       });
       await workspaces.pull({
         workspaceId: props.workspace.workspaceId,
         authInfo,
         insecurelyDisableTlsCertificateValidation,
+        disableEncoding,
       });
 
       props.onClose();
@@ -231,6 +271,7 @@ If you are, it means that creating this Snippet failed and it can safely be dele
     authProvider,
     createGitHubGist,
     createBitbucketSnippet,
+    createGitlabSnippet,
     workspaces,
     props,
     gitConfig,
@@ -254,6 +295,7 @@ If you are, it means that creating this Snippet failed and it can safely be dele
       titleIconVariant={switchExpression(authProvider.type, {
         bitbucket: BitbucketIcon,
         github: GithubIcon,
+        gitlab: GitlabIcon,
       })}
       description={i18n.createGistOrSnippetModal[authProvider.type].description(props.workspace.name)}
       actions={[
@@ -293,6 +335,7 @@ If you are, it means that creating this Snippet failed and it can safely be dele
             workspace={props.workspace}
             onSelect={setSelectedOrganization}
             readonly={authProvider.type === AuthProviderType.github}
+            actionType="snippet"
           />
           <FormHelperText>
             <HelperText>
diff --git a/packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGitRepositoryModal.tsx b/packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGitRepositoryModal.tsx
index 31e41c27e8d..deb3fb99a35 100644
--- a/packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGitRepositoryModal.tsx
+++ b/packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGitRepositoryModal.tsx
@@ -38,6 +38,7 @@ import { useAuthSession } from "../../../authSessions/AuthSessionsContext";
 import { useBitbucketClient } from "../../../bitbucket/Hooks";
 import { BitbucketIcon } from "@patternfly/react-icons/dist/js/icons/bitbucket-icon";
 import { GithubIcon } from "@patternfly/react-icons/dist/js/icons/github-icon";
+import { GitlabIcon } from "@patternfly/react-icons/dist/js/icons/gitlab-icon";
 import { useGitHubClient } from "../../../github/Hooks";
 import { AuthProviderGroup, isSupportedGitAuthProviderType } from "../../../authProviders/AuthProvidersApi";
 import { useAuthProvider } from "../../../authProviders/AuthProvidersContext";
@@ -45,6 +46,7 @@ import { switchExpression } from "@kie-tools-core/switch-expression-ts";
 import { useOnlineI18n } from "../../../i18n";
 import { LoadOrganizationsSelect, SelectOptionObjectType } from "./LoadOrganizationsSelect";
 import { useGitIntegration } from "./GitIntegrationContextProvider";
+import { useGitlabClient } from "../../../gitlab/useGitlabClient";
 import { HelperText, HelperTextItem } from "@patternfly/react-core/dist/js/components/HelperText";
 
 export interface CreateRepositoryResponse {
@@ -69,6 +71,7 @@ export function CreateGitRepositoryModal(props: {
   const authProvider = useAuthProvider(authSession);
   const bitbucketClient = useBitbucketClient(authSession);
   const gitHubClient = useGitHubClient(authSession);
+  const gitlabClient = useGitlabClient(authSession);
 
   const [isPrivate, setPrivate] = useState(false);
   const [isLoading, setLoading] = useState(false);
@@ -89,7 +92,12 @@ export function CreateGitRepositoryModal(props: {
     if (selectedOrganization?.kind !== "organization") {
       throw new Error("No workspace was selected for Bitbucket Repository.");
     }
-    const repoResponse = await bitbucketClient.createRepo({ name, workspace: selectedOrganization.value, isPrivate });
+    const bitbucketWorkspace = (selectedOrganization as SelectOptionObjectType<"organization">).selectedOption;
+    const repoResponse = await bitbucketClient.createRepo({
+      name,
+      workspace: bitbucketWorkspace.name,
+      isPrivate,
+    });
     if (!repoResponse.ok) {
       throw new Error(
         `Bitbucket repository creation request failed with: ${repoResponse.status} ${repoResponse.statusText}`
@@ -108,13 +116,33 @@ export function CreateGitRepositoryModal(props: {
     return { cloneUrl, htmlUrl: repo.links.html.href };
   }, [bitbucketClient, isPrivate, name, selectedOrganization]);
 
+  const createGitlabRepository = useCallback(async (): Promise<CreateRepositoryResponse> => {
+    const gitlabGroup = (selectedOrganization as SelectOptionObjectType<"organization">).selectedOption;
+    const repoResponse = await gitlabClient.createRepository({
+      name,
+      groupId: gitlabGroup.value,
+      visibility: isPrivate ? "private" : "public",
+    });
+    if (!(repoResponse.status === 201)) {
+      throw new Error(
+        `Gitlab repository creation request failed with: ${repoResponse.status} ${repoResponse.statusText}`
+      );
+    }
+    const repo = await repoResponse.json();
+    if (!repo?.http_url_to_repo || !repo?.web_url) {
+      throw new Error("Unexpected contents of the Gitlab repository creation response.");
+    }
+    return { cloneUrl: repo?.http_url_to_repo, htmlUrl: repo?.web_url };
+  }, [gitlabClient, isPrivate, name, selectedOrganization]);
+
   const createGitHubRepository = useCallback(async (): Promise<CreateRepositoryResponse> => {
+    const githubOrg = (selectedOrganization as SelectOptionObjectType<"organization">).selectedOption;
     const repo =
       selectedOrganization?.kind === "organization"
         ? await gitHubClient.repos.createInOrg({
             name,
             private: isPrivate,
-            org: selectedOrganization.value,
+            org: githubOrg.name,
           })
         : await gitHubClient.repos.createForAuthenticatedUser({ name, private: isPrivate });
 
@@ -134,11 +162,12 @@ export function CreateGitRepositoryModal(props: {
     if (selectedOrganization?.kind !== "organization") {
       throw new Error("No workspace was selected for Bitbucket Repository.");
     }
+    const org = (selectedOrganization as SelectOptionObjectType<"organization">).selectedOption;
     // need an empty commit push through REST API first
     await bitbucketClient
       .pushEmptyCommit({
         repository: name,
-        workspace: selectedOrganization.value,
+        workspace: org.name,
         branch: props.workspace.origin.branch,
       })
       .then((response) => {
@@ -157,12 +186,15 @@ export function CreateGitRepositoryModal(props: {
       const insecurelyDisableTlsCertificateValidation =
         authProvider?.group === AuthProviderGroup.GIT && authProvider.insecurelyDisableTlsCertificateValidation;
 
+      const disableEncoding = authProvider?.group === AuthProviderGroup.GIT && authProvider.disableEncoding;
+
       setError(undefined);
       setLoading(true);
 
       const createRepositoryCommand: () => Promise<CreateRepositoryResponse> = switchExpression(authProvider?.type, {
         bitbucket: createBitbucketRepository,
         github: createGitHubRepository,
+        gitlab: createGitlabRepository,
       });
 
       if (!createRepositoryCommand) {
@@ -195,9 +227,11 @@ export function CreateGitRepositoryModal(props: {
         force: switchExpression(authProvider?.type, {
           github: false,
           bitbucket: true,
+          gitlab: true,
         }),
         authInfo,
         insecurelyDisableTlsCertificateValidation,
+        disableEncoding,
       });
 
       await workspaces.initGitOnWorkspace({
@@ -205,6 +239,7 @@ export function CreateGitRepositoryModal(props: {
         remoteUrl: new URL(cloneUrl),
         branch: props.workspace.origin.branch,
         insecurelyDisableTlsCertificateValidation,
+        disableEncoding,
       });
 
       await workspaces.renameWorkspace({
@@ -228,6 +263,7 @@ export function CreateGitRepositoryModal(props: {
     authProvider,
     createBitbucketRepository,
     createGitHubRepository,
+    createGitlabRepository,
     pushEmptyCommitIntoBitbucket,
     workspaces,
     props,
@@ -264,6 +300,7 @@ export function CreateGitRepositoryModal(props: {
       titleIconVariant={switchExpression(authProvider.type, {
         bitbucket: BitbucketIcon,
         github: GithubIcon,
+        gitlab: GitlabIcon,
       })}
       description={i18n.createGitRepositoryModal[authProvider.type].description(props.workspace.name)}
       actions={[
@@ -275,6 +312,7 @@ export function CreateGitRepositoryModal(props: {
           isDisabled={switchExpression(authProvider.type, {
             bitbucket: !isNameValid || selectedOrganization === undefined,
             github: !isNameValid,
+            gitlab: !isNameValid,
           })}
         >
           {i18n.createGitRepositoryModal.form.buttonCreate}
@@ -302,7 +340,11 @@ export function CreateGitRepositoryModal(props: {
           </FormAlert>
         )}
         <FormGroup label={i18n.createGitRepositoryModal[authProvider.type].form.select.label} fieldId="organization">
-          <LoadOrganizationsSelect workspace={props.workspace} onSelect={setSelectedOrganization} />
+          <LoadOrganizationsSelect
+            workspace={props.workspace}
+            onSelect={setSelectedOrganization}
+            actionType="repository"
+          />
           <FormHelperText>
             <HelperText>
               <HelperTextItem variant="default">
diff --git a/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationAlerts.tsx b/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationAlerts.tsx
index 68a15e004a7..185038bdb40 100644
--- a/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationAlerts.tsx
+++ b/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationAlerts.tsx
@@ -237,6 +237,7 @@ export function useGitIntegrationAlerts(workspace: ActiveWorkspace) {
             title={switchExpression(workspace.descriptor.origin.kind, {
               GITHUB_GIST: i18n.editorPage.alerts.createGist,
               BITBUCKET_SNIPPET: i18n.editorPage.alerts.createSnippet,
+              GITLAB_SNIPPET: i18n.editorPage.alerts.createSnippet,
             })}
             actionClose={<AlertActionCloseButton onClose={close} />}
             actionLinks={
@@ -264,7 +265,13 @@ export function useGitIntegrationAlerts(workspace: ActiveWorkspace) {
           return <></>;
         }
 
-        const gistOrSnippetUrl = workspace.descriptor.origin.url;
+        const gistOrSnippetUrl = switchExpression(workspace.descriptor.origin.kind, {
+          // Remove the `.git` extension from GitLab snippet URLs.
+          // If a snippet URL ends with `.git`, GitLab may return a 404 error when accessed.
+          // This ensures only the extension is removed, not other parts of the URL.
+          GITLAB_SNIPPET: workspace.descriptor.origin.url?.replace?.(/\.git$/, ""),
+          default: workspace.descriptor.origin.url,
+        });
         return (
           <Alert
             variant="info"
@@ -275,6 +282,7 @@ export function useGitIntegrationAlerts(workspace: ActiveWorkspace) {
                 {switchExpression(workspace.descriptor.origin.kind, {
                   BITBUCKET_SNIPPET: "Snippet",
                   GITHUB_GIST: "Gist",
+                  GITLAB_SNIPPET: "Snippet",
                 })}
                 ...
               </>
@@ -299,13 +307,20 @@ export function useGitIntegrationAlerts(workspace: ActiveWorkspace) {
           return <></>;
         }
 
-        const gistOrSnippetUrl = workspace.descriptor.origin.url;
+        const gistOrSnippetUrl = switchExpression(workspace.descriptor.origin.kind, {
+          // Remove the `.git` extension from GitLab snippet URLs.
+          // If a snippet URL ends with `.git`, GitLab may return a 404 error when accessed.
+          // This ensures only the extension is removed, not other parts of the URL.
+          GITLAB_SNIPPET: workspace.descriptor.origin.url?.replace?.(/\.git$/, ""),
+          default: workspace.descriptor.origin.url,
+        });
         return (
           <Alert
             variant="success"
             title={switchExpression(workspace.descriptor.origin.kind, {
               GITHUB_GIST: i18n.editorPage.alerts.updateGist,
               BITBUCKET_SNIPPET: i18n.editorPage.alerts.updateSnippet,
+              GITLAB_SNIPPET: i18n.editorPage.alerts.updateSnippet,
             })}
             actionClose={<AlertActionCloseButton onClose={close} />}
             actionLinks={
@@ -335,6 +350,7 @@ export function useGitIntegrationAlerts(workspace: ActiveWorkspace) {
             title={switchExpression(workspace.descriptor.origin.kind as WorkspaceKindGistLike, {
               GITHUB_GIST: i18n.editorPage.alerts.errorPushingGist,
               BITBUCKET_SNIPPET: i18n.editorPage.alerts.errorPushingSnippet,
+              GITLAB_SNIPPET: i18n.editorPage.alerts.errorPushingSnippet,
             })}
             actionLinks={[
               <AlertActionLink
diff --git a/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationContextProvider.tsx b/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationContextProvider.tsx
index 4017e5456e7..ca4541e529a 100644
--- a/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationContextProvider.tsx
+++ b/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationContextProvider.tsx
@@ -55,6 +55,7 @@ import { useNavigate } from "react-router-dom";
 import { useGitIntegrationAlerts } from "./GitIntegrationAlerts";
 import { AuthProviderGroup, isGistEnabledAuthProviderType } from "../../../authProviders/AuthProvidersApi";
 import { useEditorToolbarDispatchContext } from "../EditorToolbarContextProvider";
+import { useGitlabClient } from "../../../gitlab/useGitlabClient";
 
 export type GitIntegrationContextType = {
   workspaceImportableUrl: ImportableUrl;
@@ -103,12 +104,14 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
 
   const gitHubClient = useGitHubClient(authSession);
   const bitbucketClient = useBitbucketClient(authSession);
+  const gitlabClient = useGitlabClient(authSession);
 
   const [isGistOrSnippetLoading, setGistOrSnippetLoading] = useState(false);
   const [gitHubGist, setGitHubGist] = useState<
     OctokitRestEndpointMethodTypes["gists"]["get"]["response"]["data"] | undefined
   >(undefined);
   const [bitbucketSnippet, setBitbucketSnippet] = useState<any>(undefined);
+  const [gitlabSnippet, setGitlabSnippet] = useState<any>(undefined);
 
   const insecurelyDisableTlsCertificateValidation = useMemo(() => {
     if (authProvider?.group === AuthProviderGroup.GIT) {
@@ -117,6 +120,13 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
     return props.workspace.descriptor.gitInsecurelyDisableTlsCertificateValidation;
   }, [authProvider, props.workspace]);
 
+  const disableEncoding = useMemo(() => {
+    if (authProvider?.group === AuthProviderGroup.GIT) {
+      return authProvider.disableEncoding;
+    }
+    return props.workspace.descriptor.gitDisableEncoding;
+  }, [authProvider, props.workspace]);
+
   useCancelableEffect(
     useCallback(
       ({ canceled }) => {
@@ -169,6 +179,31 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
     )
   );
 
+  useCancelableEffect(
+    useCallback(
+      ({ canceled }) => {
+        if (gitlabSnippet || workspaceImportableUrl.type !== UrlType.GITLAB_DOT_COM_SNIPPET) {
+          return;
+        }
+
+        const { snippetId, group, project } = workspaceImportableUrl;
+
+        if (!snippetId) {
+          return;
+        }
+
+        gitlabClient.getSnippet({ snippetId, group, project }).then(async (response) => {
+          if (canceled.get()) {
+            return;
+          }
+          const json = await response.json();
+          setGitlabSnippet(json);
+        });
+      },
+      [gitlabSnippet, workspaceImportableUrl, gitlabClient]
+    )
+  );
+
   const authSessionSelectFilter = useMemo(() => {
     if (!props.workspace) {
       return gitAuthSessionSelectFilter();
@@ -196,8 +231,15 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
       );
     }
 
+    if (props.workspace.descriptor.origin.kind === WorkspaceKind.GITLAB_SNIPPET) {
+      return authSessionsSelectFilterCompatibleWithGistOrSnippetUrlDomain(
+        new URL(props.workspace.descriptor.origin.url).host,
+        gitlabSnippet?.author?.username
+      );
+    }
+
     return gitAuthSessionSelectFilter();
-  }, [bitbucketSnippet?.owner?.login, gitHubGist?.owner?.login, props.workspace]);
+  }, [bitbucketSnippet?.owner?.login, gitHubGist?.owner?.login, gitlabSnippet?.author?.username, props.workspace]);
 
   const changeGitAuthSessionId = useCallback(
     (newGitAuthSessionId: React.SetStateAction<string | undefined>, lastAuthSessionId: string | undefined) => {
@@ -206,9 +248,10 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
         gitAuthSessionId:
           typeof newGitAuthSessionId === "function" ? newGitAuthSessionId(lastAuthSessionId) : newGitAuthSessionId,
         insecurelyDisableTlsCertificateValidation,
+        disableEncoding,
       });
     },
-    [props.workspace.descriptor.workspaceId, workspaces, insecurelyDisableTlsCertificateValidation]
+    [props.workspace.descriptor.workspaceId, workspaces, insecurelyDisableTlsCertificateValidation, disableEncoding]
   );
 
   const workspaceHasNestedDirectories = useMemo(
@@ -220,9 +263,11 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
 
   const canCreateBitbucketRepository = useMemo(() => authProvider?.type === "bitbucket", [authProvider?.type]);
 
+  const canCreateGitlabRepository = useMemo(() => authProvider?.type === "gitlab", [authProvider?.type]);
+
   const canCreateGitRepository = useMemo(
-    () => canCreateGitHubRepository || canCreateBitbucketRepository,
-    [canCreateGitHubRepository, canCreateBitbucketRepository]
+    () => canCreateGitHubRepository || canCreateBitbucketRepository || canCreateGitlabRepository,
+    [canCreateGitHubRepository, canCreateBitbucketRepository, canCreateGitlabRepository]
   );
 
   const canPushToGitRepository = useMemo(
@@ -238,7 +283,11 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
     return authInfo?.uuid && bitbucketSnippet?.creator.uuid === authInfo.uuid;
   }, [authInfo, bitbucketSnippet]);
 
-  const isGistOrSnippetOwner = isGitHubGistOwner || isBitbucketSnippetOwner;
+  const isGitlabSnippetOwner = useMemo(() => {
+    return authInfo?.username && gitlabSnippet?.author?.username === authInfo.username;
+  }, [authInfo, gitlabSnippet]);
+
+  const isGistOrSnippetOwner = isGitHubGistOwner || isBitbucketSnippetOwner || isGitlabSnippetOwner;
 
   const canCreateGistOrSnippet = useMemo(
     () =>
@@ -301,6 +350,7 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
           force: false,
           authInfo,
           insecurelyDisableTlsCertificateValidation,
+          disableEncoding,
         });
 
         navigate({
@@ -327,6 +377,7 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
       navigate,
       routes.import,
       insecurelyDisableTlsCertificateValidation,
+      disableEncoding,
     ]
   );
 
@@ -349,6 +400,7 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
           workspaceId: props.workspace.descriptor.workspaceId,
           authInfo,
           insecurelyDisableTlsCertificateValidation,
+          disableEncoding,
         });
 
         if (args.showAlerts) {
@@ -379,6 +431,7 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
       canPushToGitRepository,
       pushNewBranch,
       insecurelyDisableTlsCertificateValidation,
+      disableEncoding,
     ]
   );
 
@@ -408,6 +461,7 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
         force: false,
         authInfo,
         insecurelyDisableTlsCertificateValidation,
+        disableEncoding,
       });
       await pullFromGitRepository({ showAlerts: false });
       alerts.pushSuccessAlert.show();
@@ -427,6 +481,7 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
     gitConfig,
     pullFromGitRepository,
     insecurelyDisableTlsCertificateValidation,
+    disableEncoding,
   ]);
 
   const forceUpdateGistOrSnippet = useCallback(async () => {
@@ -444,12 +499,14 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
         remoteRef: `refs/heads/${props.workspace.descriptor.origin.branch}`,
         force: true,
         authInfo,
+        disableEncoding,
       });
 
       await workspaces.pull({
         workspaceId: props.workspace.descriptor.workspaceId,
         authInfo,
         insecurelyDisableTlsCertificateValidation,
+        disableEncoding,
       });
       alerts.successfullyUpdatedGistOrSnippetAlert.show();
     } catch (e) {
@@ -466,6 +523,7 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
     setSyncGistOrSnippetDropdownOpen,
     workspaces,
     insecurelyDisableTlsCertificateValidation,
+    disableEncoding,
   ]);
 
   const updateGistOrSnippet = useCallback(async () => {
@@ -493,11 +551,13 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
         force: false,
         authInfo,
         insecurelyDisableTlsCertificateValidation,
+        disableEncoding,
       });
 
       await workspaces.pull({
         workspaceId: props.workspace.descriptor.workspaceId,
         authInfo,
+        disableEncoding,
       });
     } catch (e) {
       alerts.errorPushingGistOrSnippet.show({ forceUpdateGistOrSnippet });
@@ -519,6 +579,7 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
     forceUpdateGistOrSnippet,
     setSyncGistOrSnippetDropdownOpen,
     insecurelyDisableTlsCertificateValidation,
+    disableEncoding,
   ]);
 
   const forkGitHubGist = useCallback(async () => {
@@ -559,6 +620,7 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
         force: true,
         authInfo,
         insecurelyDisableTlsCertificateValidation,
+        disableEncoding,
       });
 
       // Redirect to import workspace
@@ -590,6 +652,7 @@ export function GitIntegrationContextProvider(props: GitIntegrationContextProvid
     routes.import,
     alerts.errorAlert,
     insecurelyDisableTlsCertificateValidation,
+    disableEncoding,
   ]);
 
   useEffect(() => {
diff --git a/packages/online-editor/src/editor/Toolbar/GitIntegration/LoadOrganizationsSelect.tsx b/packages/online-editor/src/editor/Toolbar/GitIntegration/LoadOrganizationsSelect.tsx
index 06fcd2c980a..6212c4df66e 100644
--- a/packages/online-editor/src/editor/Toolbar/GitIntegration/LoadOrganizationsSelect.tsx
+++ b/packages/online-editor/src/editor/Toolbar/GitIntegration/LoadOrganizationsSelect.tsx
@@ -36,31 +36,43 @@ import { SyncAltIcon } from "@patternfly/react-icons/dist/js/icons/sync-alt-icon
 import { UserIcon } from "@patternfly/react-icons/dist/js/icons/user-icon";
 import { UsersIcon } from "@patternfly/react-icons/dist/js/icons/users-icon";
 import { useOnlineI18n } from "../../../i18n";
+import GitlabIcon from "@patternfly/react-icons/dist/js/icons/gitlab-icon";
+import { useGitlabClient } from "../../../gitlab/useGitlabClient";
 
+export type Organization = {
+  name: string;
+  value: string;
+};
 export interface LoadOrganizationsReponse {
-  organizations: {
-    name: string;
-  }[];
+  organizations: Organization[];
 }
+type KindToValueMap = {
+  user: string;
+  organization: Organization;
+};
 
 export type SelectOptionKindType = "user" | "organization";
 
-export type SelectOptionObjectType = {
-  value: string;
-  kind: SelectOptionKindType;
+export type SelectOptionObjectType<K extends SelectOptionKindType = SelectOptionKindType> = {
+  selectedOption: KindToValueMap[K];
+  kind: K;
   toString(): string;
   compareTo(selectOption: any): boolean;
 };
 
-const getSelectOptionValue = (value: string, kind: SelectOptionKindType): SelectOptionObjectType => {
+const getSelectOptionValue = <K extends SelectOptionKindType>(
+  selectedOption: KindToValueMap[K],
+  kind: K
+): SelectOptionObjectType<K> => {
   return {
-    value,
+    selectedOption,
     kind,
     toString: () => {
-      return value;
+      return kind === "user" ? (selectedOption as string) : (selectedOption as Organization).name;
     },
     compareTo: (selectOption: any) => {
-      return value.toLowerCase() === selectOption.toString().toLowerCase();
+      const val = kind === "user" ? (selectedOption as string) : (selectedOption as Organization).name;
+      return val.toLowerCase() === selectOption.toString().toLowerCase();
     },
   };
 };
@@ -70,18 +82,20 @@ export interface Props {
   onSelect: (organization?: SelectOptionObjectType) => void;
   readonly?: boolean;
   hideUser?: boolean;
+  actionType?: "repository" | "snippet";
 }
 
-export const LoadOrganizationsSelect = (props: Props) => {
-  const { authSession, authInfo } = useAuthSession(props.workspace.gitAuthSessionId);
+export const LoadOrganizationsSelect = ({ onSelect, workspace, readonly, actionType }: Props) => {
+  const { authSession, authInfo } = useAuthSession(workspace.gitAuthSessionId);
   const authProvider = useAuthProvider(authSession);
   const gitHubClient = useGitHubClient(authSession);
   const bitbucketClient = useBitbucketClient(authSession);
+  const gitlabClient = useGitlabClient(authSession);
 
   const { i18n } = useOnlineI18n();
 
   const [isOrganizationDropdownOpen, setOrganizationDropdownOpen] = useState(false);
-  const [organizations, setOrganizations] = useState<{ name: string }[]>();
+  const [organizations, setOrganizations] = useState<Organization[]>();
   const [isLoadingOrganizations, setLoadingOrganizations] = useState(false);
   const [internalSelectedOption, setInternalSelectedOption] = useState<SelectOptionObjectType>();
 
@@ -89,9 +103,14 @@ export const LoadOrganizationsSelect = (props: Props) => {
     return authProvider?.type === AuthProviderType.bitbucket;
   }, [authProvider?.type]);
 
+  const isGitlabSnippet = useMemo(
+    () => authProvider?.type === AuthProviderType.gitlab && actionType === "snippet",
+    [authProvider?.type, actionType]
+  );
+
   const getGitHubOrganizationsForUser = useCallback(async (): Promise<LoadOrganizationsReponse> => {
     const orgs = await gitHubClient.orgs.listForAuthenticatedUser();
-    return { organizations: orgs.data.map((it) => ({ name: it.login })) };
+    return { organizations: orgs.data.map((it) => ({ name: it.login, value: it.login })) };
   }, [gitHubClient.orgs]);
 
   const getBitbucketWorkspacesForUser = useCallback(async (): Promise<LoadOrganizationsReponse> => {
@@ -102,10 +121,34 @@ export const LoadOrganizationsSelect = (props: Props) => {
       return emptyResponse;
     }
     const values: any[] = json.values;
-    return { organizations: values.map((it) => ({ name: it.workspace.slug })) };
+    return { organizations: values.map((it) => ({ name: it.workspace.slug, value: it.workspace.slug })) };
   }, [bitbucketClient]);
 
-  const { onSelect } = props;
+  const getGitlabGroupsForUser = useCallback(async (): Promise<LoadOrganizationsReponse> => {
+    if (actionType && actionType === "snippet") {
+      const projectsResponse = await gitlabClient.listProjects();
+      const projectsResponseJson: any[] = await projectsResponse.json();
+      return {
+        organizations: (projectsResponseJson ?? [])
+          .map((project) => ({
+            name: project?.name_with_namespace,
+            value: project?.id,
+          }))
+          .sort((a, b) => a?.name?.localeCompare?.(b?.name)),
+      };
+    }
+    const groupsResponse = await gitlabClient.listGroups();
+    const groupsResponseJson: any[] = await groupsResponse.json();
+    return {
+      organizations: (groupsResponseJson ?? [])
+        .map((group) => ({
+          name: group?.full_name,
+          value: group?.id,
+        }))
+        .sort((a, b) => a?.name?.localeCompare?.(b?.name)),
+    };
+  }, [gitlabClient, actionType]);
+
   const setSelectedOption = useCallback(
     (option?: SelectOptionObjectType) => {
       onSelect(option);
@@ -119,10 +162,13 @@ export const LoadOrganizationsSelect = (props: Props) => {
       if (!isSupportedGitAuthProviderType(authProvider?.type)) {
         return;
       }
+      const defaultSelectedOptionValue = orgs?.organizations?.[0] ?? authInfo?.username;
+      const defaultSelectedOptionKind = orgs?.organizations?.[0] ? "organization" : "user";
       setSelectedOption(
         switchExpression(authProvider?.type, {
-          bitbucket: getSelectOptionValue(orgs.organizations[0].name, "organization"),
+          bitbucket: getSelectOptionValue(orgs.organizations[0], "organization"),
           github: getSelectOptionValue(authInfo!.username, "user"),
+          gitlab: getSelectOptionValue(defaultSelectedOptionValue, defaultSelectedOptionKind),
         })
       );
     },
@@ -137,6 +183,7 @@ export const LoadOrganizationsSelect = (props: Props) => {
     switchExpression(authProvider?.type, {
       bitbucket: getBitbucketWorkspacesForUser,
       github: getGitHubOrganizationsForUser,
+      gitlab: getGitlabGroupsForUser,
     })()
       .then((it) => {
         setOrganizations(it.organizations);
@@ -145,7 +192,13 @@ export const LoadOrganizationsSelect = (props: Props) => {
       .finally(() => {
         setLoadingOrganizations(false);
       });
-  }, [authProvider?.type, getBitbucketWorkspacesForUser, getGitHubOrganizationsForUser, selectDefaultOption]);
+  }, [
+    authProvider?.type,
+    getBitbucketWorkspacesForUser,
+    getGitHubOrganizationsForUser,
+    getGitlabGroupsForUser,
+    selectDefaultOption,
+  ]);
 
   useEffect(() => {
     setOrganizations(undefined);
@@ -177,9 +230,12 @@ export const LoadOrganizationsSelect = (props: Props) => {
         options.push(<Divider component="li" key={1} />);
       }
       options.push(
-        <SelectGroup label={i18n.loadOrganizationsSelect[authProvider.type].organizations} key="group2">
+        <SelectGroup
+          label={isGitlabSnippet ? "GitLab Projects" : i18n.loadOrganizationsSelect[authProvider.type].organizations}
+          key="group2"
+        >
           {organizations?.map((it, index) => (
-            <SelectOption key={2 + index} value={getSelectOptionValue(it.name, "organization")}>
+            <SelectOption key={2 + index} value={getSelectOptionValue(it, "organization")}>
               <Flex>
                 <FlexItem>
                   <UsersIcon />
@@ -192,7 +248,7 @@ export const LoadOrganizationsSelect = (props: Props) => {
       );
     }
     return options;
-  }, [authInfo, authProvider, hideUser, i18n.loadOrganizationsSelect, organizations]);
+  }, [authInfo, authProvider, hideUser, i18n.loadOrganizationsSelect, organizations, isGitlabSnippet]);
 
   if (!authProvider || !isSupportedGitAuthProviderType(authProvider?.type)) {
     return <></>;
@@ -211,10 +267,11 @@ export const LoadOrganizationsSelect = (props: Props) => {
             toggleIcon={switchExpression(authProvider.type, {
               bitbucket: <BitbucketIcon />,
               github: <GithubIcon />,
+              gitlab: <GitlabIcon />,
             })}
             onToggle={(_event, val) => setOrganizationDropdownOpen(val)}
             selections={internalSelectedOption}
-            isDisabled={props.readonly}
+            isDisabled={readonly}
           >
             {selectOptions}
           </Select>
@@ -227,7 +284,7 @@ export const LoadOrganizationsSelect = (props: Props) => {
           size="sm"
           isLoading={isLoadingOrganizations}
           onClick={loadOrganizations}
-          isDisabled={props.readonly}
+          isDisabled={readonly}
         >
           {isLoadingOrganizations ? "" : <SyncAltIcon />}
         </Button>
diff --git a/packages/online-editor/src/editor/Toolbar/NewFileDropdownMenu.tsx b/packages/online-editor/src/editor/Toolbar/NewFileDropdownMenu.tsx
index cf08374e0f5..ac9014561dc 100644
--- a/packages/online-editor/src/editor/Toolbar/NewFileDropdownMenu.tsx
+++ b/packages/online-editor/src/editor/Toolbar/NewFileDropdownMenu.tsx
@@ -52,6 +52,7 @@ import { useBitbucketClient } from "../../bitbucket/Hooks";
 import { isEditable } from "../../envelopeLocator/EditorEnvelopeLocatorFactory";
 import { useEditorsConfig } from "../../envelopeLocator/hooks/EditorEnvelopeLocatorContext";
 import { useEnv } from "../../env/hooks/EnvContext";
+import { useGitlabClient } from "../../gitlab/useGitlabClient";
 
 const ROOT_MENU_ID = "addFileRootMenu";
 
@@ -200,6 +201,8 @@ export function NewFileDropdownMenu(props: {
         UrlType.GITHUB_DOT_COM_FILE,
         UrlType.BITBUCKET_DOT_ORG_FILE,
         UrlType.BITBUCKET_DOT_ORG_SNIPPET_FILE,
+        UrlType.GITLAB_DOT_COM_FILE,
+        UrlType.GITLAB_DOT_COM_SNIPPET_FILE,
       ],
       []
     )
@@ -208,6 +211,7 @@ export function NewFileDropdownMenu(props: {
   const { authSession } = useAuthSession(authSessionId);
   const gitHubClient = useGitHubClient(authSession);
   const bitbucketClient = useBitbucketClient(authSession);
+  const gitlabClient = useGitlabClient(authSession);
 
   // Select authSession based on the importableUrl domain (begin)
   const authProviders = useAuthProviders();
@@ -240,7 +244,12 @@ export function NewFileDropdownMenu(props: {
       setImportingError(undefined);
 
       try {
-        const { error, rawUrl, content } = await fetchSingleFileContent(importableUrl, gitHubClient, bitbucketClient);
+        const { error, rawUrl, content } = await fetchSingleFileContent(
+          importableUrl,
+          gitHubClient,
+          bitbucketClient,
+          gitlabClient
+        );
         if (error) {
           setImportingError(error);
           return;
@@ -263,7 +272,7 @@ export function NewFileDropdownMenu(props: {
         setImporting(false);
       }
     },
-    [gitHubClient, bitbucketClient, workspaces, props]
+    [gitHubClient, bitbucketClient, gitlabClient, workspaces, props]
   );
 
   const sampleUrl = useCallback(
diff --git a/packages/online-editor/src/editor/Toolbar/Share/GitDropdownGroup.tsx b/packages/online-editor/src/editor/Toolbar/Share/GitDropdownGroup.tsx
index c5afcf0ae78..551dc28cb2b 100644
--- a/packages/online-editor/src/editor/Toolbar/Share/GitDropdownGroup.tsx
+++ b/packages/online-editor/src/editor/Toolbar/Share/GitDropdownGroup.tsx
@@ -38,6 +38,7 @@ import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
 import { switchExpression } from "@kie-tools-core/switch-expression-ts";
 import BitbucketIcon from "@patternfly/react-icons/dist/js/icons/bitbucket-icon";
 import GithubIcon from "@patternfly/react-icons/dist/js/icons/github-icon";
+import { GitlabIcon } from "@patternfly/react-icons/dist/js/icons/gitlab-icon";
 import GitIcon from "@patternfly/react-icons/dist/js/icons/git-icon";
 import { useAuthSession } from "../../../authSessions/AuthSessionsContext";
 import { useAuthProvider } from "../../../authProviders/AuthProvidersContext";
@@ -95,7 +96,7 @@ export const GitDropdownGroup = (props: Props) => {
             />
           }
         >
-          {`Manage authentication sources for '${props.workspace.descriptor.name}' to be able to create Repository, GitHub Gist or Bitbucket Snippet.`}
+          {`Manage authentication sources for '${props.workspace.descriptor.name}' to be able to create Repository, GitHub Gist, Bitbucket Snippet or GitLab Snippet.`}
         </Alert>
         {canCreateGitRepository && (
           <Tooltip
@@ -109,6 +110,7 @@ export const GitDropdownGroup = (props: Props) => {
               icon={switchExpression(authProvider?.type as GitAuthProviderType, {
                 bitbucket: <BitbucketIcon />,
                 github: <GithubIcon />,
+                gitlab: <GitlabIcon />,
                 default: <GitIcon />,
               })}
               data-testid={"create-git-repository-button"}
@@ -120,6 +122,7 @@ export const GitDropdownGroup = (props: Props) => {
               {switchExpression(authProvider?.type as GitAuthProviderType, {
                 github: "GitHub repository",
                 bitbucket: "Bitbucket repository",
+                gitlab: "GitLab repository",
                 default: "Git repository",
               })}
               ...
@@ -135,6 +138,7 @@ export const GitDropdownGroup = (props: Props) => {
                 {switchExpression(authProvider?.type as GistEnabledAuthProviderType, {
                   github: i18n.editorToolbar.cantCreateGistTooltip,
                   bitbucket: i18n.editorToolbar.cantCreateSnippetTooltip,
+                  gitlab: i18n.editorToolbar.cantCreateSnippetTooltip,
                 })}
               </div>
             }
@@ -145,6 +149,7 @@ export const GitDropdownGroup = (props: Props) => {
               icon={switchExpression(authProvider?.type as GistEnabledAuthProviderType, {
                 bitbucket: <BitbucketIcon />,
                 github: <GithubIcon />,
+                gitlab: <GitlabIcon />,
               })}
               data-testid={"create-gist-or-snippet-button"}
               component="button"
@@ -154,6 +159,7 @@ export const GitDropdownGroup = (props: Props) => {
               {switchExpression(authProvider?.type as GistEnabledAuthProviderType, {
                 github: i18n.editorToolbar.createGist,
                 bitbucket: i18n.editorToolbar.createSnippet,
+                gitlab: i18n.editorToolbar.createSnippet,
               })}
             </DropdownItem>
           </Tooltip>
diff --git a/packages/online-editor/src/editor/Toolbar/SyncDropdownMenu.tsx b/packages/online-editor/src/editor/Toolbar/SyncDropdownMenu.tsx
index 0dc774d0bec..d24961eb7e5 100644
--- a/packages/online-editor/src/editor/Toolbar/SyncDropdownMenu.tsx
+++ b/packages/online-editor/src/editor/Toolbar/SyncDropdownMenu.tsx
@@ -49,6 +49,7 @@ import { useEditorToolbarContext, useEditorToolbarDispatchContext } from "./Edit
 import { useGitIntegration } from "./GitIntegration/GitIntegrationContextProvider";
 import { useAuthProvider } from "../../authProviders/AuthProvidersContext";
 import { useAuthSession } from "../../authSessions/AuthSessionsContext";
+import GitlabIcon from "@patternfly/react-icons/dist/js/icons/gitlab-icon";
 
 type Props = {
   workspace: ActiveWorkspace;
@@ -94,6 +95,7 @@ export function SyncDropdownMenu(props: Props) {
                     {switchExpression(props.workspace.descriptor.origin.kind as WorkspaceKindGistLike, {
                       GITHUB_GIST: i18n.editorToolbar.cantUpdateGistTooltip,
                       BITBUCKET_SNIPPET: i18n.editorToolbar.cantUpdateSnippetTooltip,
+                      GITLAB_SNIPPET: i18n.editorToolbar.cantUpdateSnippetTooltip,
                     })}
                   </div>
                 }
@@ -106,6 +108,7 @@ export function SyncDropdownMenu(props: Props) {
                     icon={switchExpression(props.workspace.descriptor.origin.kind as WorkspaceKindGistLike, {
                       BITBUCKET_SNIPPET: <BitbucketIcon />,
                       GITHUB_GIST: <GithubIcon />,
+                      GITLAB_SNIPPET: <GitlabIcon />,
                     })}
                     onClick={updateGistOrSnippet}
                     isDisabled={!canUpdateGistOrSnippet}
@@ -114,6 +117,7 @@ export function SyncDropdownMenu(props: Props) {
                     {switchExpression(props.workspace.descriptor.origin.kind as WorkspaceKindGistLike, {
                       BITBUCKET_SNIPPET: "Bitbucket Snippet",
                       GITHUB_GIST: "GitHub Gist",
+                      GITLAB_SNIPPET: "GitLab Snippet",
                     })}
                   </DropdownItem>
                   {canForkGitHubGist && (
@@ -169,6 +173,7 @@ export function SyncDropdownMenu(props: Props) {
                         title={`Can't Update ${switchExpression(authProvider?.type as GitAuthProviderType, {
                           github: "GitHub repository",
                           bitbucket: "Bitbucket repository",
+                          gitlab: "GitLab repository",
                           default: "Git repository",
                         })} without selecting a matching authentication source`}
                         actionLinks={
@@ -195,6 +200,7 @@ export function SyncDropdownMenu(props: Props) {
                           {
                             GITHUB_GIST: "Github Gist",
                             BITBUCKET_SNIPPET: "Bitbucket Snippet",
+                            GITLAB_SNIPPET: "GitLab Snippet",
                           }
                         )}.`}
                       </Alert>
diff --git a/packages/online-editor/src/editor/Toolbar/Workspace/Hooks.tsx b/packages/online-editor/src/editor/Toolbar/Workspace/Hooks.tsx
index c31635cb689..c31588a1fc2 100644
--- a/packages/online-editor/src/editor/Toolbar/Workspace/Hooks.tsx
+++ b/packages/online-editor/src/editor/Toolbar/Workspace/Hooks.tsx
@@ -89,6 +89,7 @@ export function useWorkspaceNavigationBlocker(workspace: ActiveWorkspace) {
                   canPush={switchExpression(workspace.descriptor.origin.kind as WorkspaceKindGitBased, {
                     BITBUCKET_SNIPPET: canUpdateGistOrSnippet,
                     GITHUB_GIST: canUpdateGistOrSnippet,
+                    GITLAB_SNIPPET: canUpdateGistOrSnippet,
                     GIT: canPushToGitRepository,
                   })}
                   remoteRef={`${GIT_ORIGIN_REMOTE_NAME}/${workspace.descriptor.origin.branch}`}
@@ -98,6 +99,7 @@ export function useWorkspaceNavigationBlocker(workspace: ActiveWorkspace) {
                     switchExpression(workspace.descriptor.origin.kind as WorkspaceKindGitBased, {
                       BITBUCKET_SNIPPET: updateGistOrSnippet,
                       GITHUB_GIST: updateGistOrSnippet,
+                      GITLAB_SNIPPET: updateGistOrSnippet,
                       GIT: pushToGitRepository,
                     })();
                   }}
diff --git a/packages/online-editor/src/github/Hooks.tsx b/packages/online-editor/src/github/Hooks.tsx
index 4c2afad381d..a83a0e46d96 100644
--- a/packages/online-editor/src/github/Hooks.tsx
+++ b/packages/online-editor/src/github/Hooks.tsx
@@ -29,6 +29,7 @@ export function getOctokitClient(args: {
   domain?: string;
   proxyUrl?: string;
   insecurelyDisableTlsCertificateValidation?: boolean;
+  disableEncoding?: boolean;
 }) {
   return new Octokit({
     auth: args.githubToken,
@@ -48,6 +49,12 @@ export function getOctokitClient(args: {
                   ).toString(),
                 }
               : {}),
+            // If disableEncoding is true, force proxy/server to skip compression
+            ...(args.disableEncoding
+              ? {
+                  [CorsProxyHeaderKeys.DISABLE_ENCODING]: Boolean(args.disableEncoding).toString(),
+                }
+              : {}),
             ...options.headers,
           },
         });
@@ -75,6 +82,7 @@ export function useGitHubClient(authSession: AuthSession | undefined): Octokit {
       githubToken: authSession.token,
       proxyUrl: authProvider.insecurelyDisableTlsCertificateValidation ? env.KIE_SANDBOX_CORS_PROXY_URL : undefined,
       insecurelyDisableTlsCertificateValidation: authProvider.insecurelyDisableTlsCertificateValidation,
+      disableEncoding: authProvider.disableEncoding,
     });
   }, [authProviders, env.KIE_SANDBOX_CORS_PROXY_URL, authSession]);
 }
diff --git a/packages/online-editor/src/gitlab/GitlabClient.ts b/packages/online-editor/src/gitlab/GitlabClient.ts
new file mode 100644
index 00000000000..01e79843b30
--- /dev/null
+++ b/packages/online-editor/src/gitlab/GitlabClient.ts
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { isEmpty } from "lodash";
+
+export interface Options {
+  appName: string;
+  token?: string;
+  domain?: string;
+  headers?: Record<string, string>;
+  proxyUrl?: string;
+}
+
+type GitlabVisibility = "private" | "internal" | "public";
+type GitlabBasePath = "/projects" | "/groups" | "/snippets";
+
+type GetSnippetArgsType = {
+  snippetId: string;
+  group?: string;
+  project?: string;
+};
+
+type GetSnippetFileArgsType = {
+  snippetId: string;
+  group?: string;
+  project?: string;
+  branch?: string;
+  filePath: string;
+};
+
+type GetRepositoryContentsArgsType = {
+  project: string;
+  ref: string;
+  path: string;
+  group?: string;
+};
+
+type CreateRepositoryArgsType = {
+  name: string;
+  groupId?: string;
+  visibility: GitlabVisibility;
+};
+
+type SnippetsFile = {
+  file_path: string;
+  content: string;
+};
+
+type CreateSnippetArgsType = {
+  title: string;
+  files: SnippetsFile[];
+  visibility: GitlabVisibility;
+  id?: string;
+};
+
+type ProjectPath = {
+  group?: string;
+  project?: string;
+};
+
+export interface GitlabClientApi {
+  appName: string;
+  token?: string;
+  domain?: string;
+  headers?: Record<string, string>;
+  getApiUrl(): string;
+  getAuthedUser(): Promise<Response>;
+  createRepository(args: CreateRepositoryArgsType): Promise<Response>;
+  getRepositoryContents(args: GetRepositoryContentsArgsType): Promise<Response>;
+  createSnippet(args: CreateSnippetArgsType): Promise<Response>;
+  getSnippet(args: GetSnippetArgsType): Promise<Response>;
+  getSnippetFile(args: GetSnippetFileArgsType): Promise<Response>;
+  getSnippetFileRaw(args: GetSnippetFileArgsType): Promise<Response>;
+  listGroups(): Promise<Response>;
+  listProjects(): Promise<Response>;
+}
+export class GitlabClient implements GitlabClientApi {
+  constructor(options: Options) {
+    this.appName = options.appName;
+    this.token = options?.token ?? "";
+    this.domain = options?.domain ?? "gitlab.com";
+    this.headers = {
+      "Content-Type": "application/json",
+      Accept: "application/json",
+      ...options?.headers,
+    };
+    this.proxyUrl = options.proxyUrl;
+  }
+  appName: string;
+  token: string;
+  domain: string;
+  headers: Record<string, string>;
+  proxyUrl?: string;
+
+  request = async (props: {
+    urlContext: string;
+    method?: string;
+    body?: any;
+    extraHeaders?: { [key: string]: string | undefined };
+  }) => {
+    const resolvedUrl = new URL(this.getApiUrl() + props.urlContext).toString();
+    const authHeader: Record<string, string> = { Authorization: "Bearer " + this.token };
+    const requestHeaders = {
+      ...this.headers,
+      ...props.extraHeaders,
+      ...authHeader,
+    };
+
+    return fetch(resolvedUrl, {
+      method: props.method,
+      headers: JSON.parse(JSON.stringify(requestHeaders)), // allows for erasing header in extraHeaders
+      body: props.body,
+    });
+  };
+
+  getApiUrl = () => {
+    if (this.proxyUrl) {
+      return `${this.proxyUrl}/${this.domain}/api/v4`;
+    }
+    return `https://${this.domain}/api/v4`;
+  };
+
+  getAuthedUser = () => this.request({ urlContext: "/user" });
+
+  createProjectPath = ({ group, project }: ProjectPath): string =>
+    encodeURIComponent([group, project].filter(Boolean).join("/"));
+
+  createProjectBasePathWithId = ({ group, project }: ProjectPath, basePath: GitlabBasePath = "/projects") => {
+    const id = this.createProjectPath({ group, project });
+    return id ? `${basePath}/${id}` : basePath;
+  };
+
+  checkSnippetLevel = ({ group, project }: ProjectPath): string => {
+    const isProjectSnippet = !isEmpty(group) || !isEmpty(project);
+    return isProjectSnippet ? this.createProjectBasePathWithId({ group, project }) : "";
+  };
+
+  getRepositoryContents = ({ project, path, ref, group }: GetRepositoryContentsArgsType) => {
+    const baseUrl = this.createProjectBasePathWithId({ group, project });
+    return this.request({
+      urlContext: `${baseUrl}/repository/files/${path}/raw?ref=${ref}`,
+      method: "get",
+    });
+  };
+
+  createRepository = ({ groupId, visibility, name }: CreateRepositoryArgsType) =>
+    this.request({
+      urlContext: `/projects`,
+      method: "post",
+      body: JSON.stringify({
+        name,
+        visibility,
+        description: `This repository was created using ${this.appName}`,
+        ...(groupId && { namespace_id: groupId }),
+      }),
+    });
+
+  createSnippet = ({ title, visibility, id, files }: CreateSnippetArgsType) => {
+    const url = id ? "/projects/" + id + "/snippets" : "/snippets";
+    return this.request({
+      urlContext: url,
+      method: "post",
+      body: JSON.stringify({
+        title,
+        description: `This snippet was created using ${this.appName}`,
+        visibility,
+        files,
+      }),
+    });
+  };
+
+  getSnippet = ({ snippetId, group, project }: GetSnippetArgsType) => {
+    const baseUrl = this.checkSnippetLevel({ group, project });
+    return this.request({
+      urlContext: `${baseUrl}/snippets/${snippetId}`,
+      method: "get",
+    });
+  };
+
+  getSnippetFile = ({ snippetId, branch, filePath, group, project }: GetSnippetFileArgsType) => {
+    const baseUrl = this.checkSnippetLevel({ group, project });
+    return this.request({
+      urlContext: `${baseUrl}/snippets/${snippetId}/files/${branch}/${filePath}`,
+      method: "get",
+    });
+  };
+
+  getSnippetFileRaw = ({ snippetId, branch, filePath, group, project }: GetSnippetFileArgsType) => {
+    const baseUrl = this.checkSnippetLevel({ group, project });
+    return this.request({
+      urlContext: `${baseUrl}/snippets/${snippetId}/files/${branch}/${filePath}/raw`,
+      method: "get",
+    });
+  };
+
+  listGroups = () =>
+    this.request({
+      urlContext: "/groups?active=true",
+      method: "get",
+    });
+
+  listProjects = () =>
+    this.request({
+      urlContext: "/projects?membership=true&&active=true",
+      method: "get",
+    });
+}
diff --git a/packages/online-editor/src/gitlab/ParseGitLabUrl.ts b/packages/online-editor/src/gitlab/ParseGitLabUrl.ts
new file mode 100644
index 00000000000..417bde15b30
--- /dev/null
+++ b/packages/online-editor/src/gitlab/ParseGitLabUrl.ts
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { matchPath } from "react-router-dom";
+import { ImportableUrl, UrlType } from "../importFromUrl/ImportableUrlHooks";
+
+const GITLAB_NAMESPACE_REGEX = "([^\\/]+(?:\\/[^\\/]+)*)"; // group or nested group(s)
+const NAMESPACE = GITLAB_NAMESPACE_REGEX;
+const PROJECT = "([^\\/]+)"; // project name
+
+const GITLAB_PROJECT_SNIPPET_REGEX = new RegExp(`^/${NAMESPACE}/${PROJECT}/snippets/(\\d+)(?:\\.git)?/?$`);
+const GITLAB_PROJECT_SNIPPET_FILE_REGEX = new RegExp(`^/${NAMESPACE}/${PROJECT}/snippets/([^/]+)/raw/([^/]+)/(.+)$`);
+const GITLAB_REPO_TREE_REGEX = new RegExp(`^/${NAMESPACE}/${PROJECT}/tree/([^/]+)$`);
+const GITLAB_REPO_FILE_REGEX = new RegExp(`^/${NAMESPACE}/${PROJECT}/blob/([^/]+)/(.*)$`);
+const GITLAB_DEFAULT_REPO_REGEX = new RegExp(`^/${NAMESPACE}/${PROJECT}$`);
+
+function ensureGitExtension(pathname: string): string {
+  // Remove any trailing slash first
+  const cleanPath = pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
+
+  // Add `.git` if not already present
+  return cleanPath.endsWith(".git") ? cleanPath : `${cleanPath}.git`;
+}
+
+export function parseGitLabUrl(url: URL): ImportableUrl {
+  // /-/ is mostly used in GitLab web URLs, not the REST API.
+  // replace all instances of /-/ with /
+  const pathname = (url.pathname = url?.pathname?.replace(/\/-\//g, "/"));
+
+  // 1. Standalone Snippet: eg: https://gitlab.com/snippets/123
+  const standaloneSnippet = matchPath(
+    {
+      path: "/snippets/:snippetId",
+      end: true,
+      caseSensitive: true,
+    },
+    pathname
+  );
+
+  if (standaloneSnippet !== null && standaloneSnippet.params.snippetId) {
+    const customStandaloneSnippetUrl = new URL(url);
+    // Without .git on GitLab → Error (not a git repository or unexpected server response)
+    // Ensure the pathname ends with `.git`
+    customStandaloneSnippetUrl.pathname = ensureGitExtension(customStandaloneSnippetUrl.pathname);
+    return {
+      type: UrlType.GITLAB_DOT_COM_SNIPPET,
+      snippetId: standaloneSnippet.params.snippetId,
+      url: customStandaloneSnippetUrl,
+    };
+  }
+
+  // 2. Standalone Snippet File: eg: https://gitlab.com/snippets/123/raw/main/sample.dmn
+  const standaloneSnippetFile = matchPath(
+    {
+      path: "/snippets/:snippetId/raw/:tree/:fileName",
+      end: true,
+      caseSensitive: true,
+    },
+    pathname
+  );
+
+  if (
+    standaloneSnippetFile !== null &&
+    standaloneSnippetFile.params.fileName &&
+    standaloneSnippetFile.params.snippetId &&
+    standaloneSnippetFile.params.tree
+  ) {
+    const {
+      params: { fileName, snippetId, tree },
+    } = standaloneSnippetFile;
+    return { type: UrlType.GITLAB_DOT_COM_SNIPPET_FILE, snippetId, branch: tree, filePath: fileName, url };
+  }
+
+  // 3. Project Snippet: eg: https://gitlab.com/group/project/-/snippets/123
+  const projectSnippetMatch = pathname.match(GITLAB_PROJECT_SNIPPET_REGEX);
+  if (projectSnippetMatch) {
+    const [, group, project, snippetId] = projectSnippetMatch ?? [];
+    if (group && project && snippetId) {
+      const customProjectSnippetUrl = new URL(url);
+      // Without .git on GitLab → Error (not a git repository or unexpected server response)
+      // Ensure the pathname ends with `.git`
+      customProjectSnippetUrl.pathname = ensureGitExtension(customProjectSnippetUrl.pathname);
+      return {
+        type: UrlType.GITLAB_DOT_COM_SNIPPET,
+        snippetId,
+        group: group,
+        project,
+        url: customProjectSnippetUrl,
+      };
+    }
+  }
+
+  // 4. Project Snippet File: eg: https://gitlab.com/group/project/-/snippets/123/raw/main/sample.dmn
+  const projectSnippetFileMatch = pathname.match(GITLAB_PROJECT_SNIPPET_FILE_REGEX);
+  if (projectSnippetFileMatch) {
+    const [, group, project, snippetId, tree, path] = projectSnippetFileMatch ?? [];
+    if (group && project && snippetId && tree && path) {
+      return {
+        type: UrlType.GITLAB_DOT_COM_SNIPPET_FILE,
+        snippetId,
+        group,
+        project,
+        branch: tree,
+        filePath: path,
+        url,
+      };
+    }
+  }
+
+  // 5. Specific branch/ref: eg: https://gitlab.com/group/project/-/tree/main
+  const repoTreeViewMatch = pathname.match(GITLAB_REPO_TREE_REGEX);
+  if (repoTreeViewMatch) {
+    const [, group, project, tree] = repoTreeViewMatch ?? [];
+    if (group && project && tree) {
+      const customGitRefNameUrl = new URL(url);
+      customGitRefNameUrl.pathname = customGitRefNameUrl.pathname.replace(`/tree/${tree}`, "");
+      // Without .git on GitLab → Error (not a git repository or unexpected server response)
+      // Ensure the pathname ends with `.git`
+      customGitRefNameUrl.pathname = ensureGitExtension(customGitRefNameUrl.pathname);
+      return {
+        type: UrlType.GITLAB_DOT_COM,
+        group,
+        project,
+        branch: tree,
+        url: customGitRefNameUrl,
+      };
+    }
+  }
+
+  // 6. File in branch: eg: https://gitlab.com/group/project/-/blob/main/src/sample.dmn
+  const repoFileViewMatch = pathname.match(GITLAB_REPO_FILE_REGEX);
+  if (repoFileViewMatch) {
+    const [, group, project, tree, path] = repoFileViewMatch ?? [];
+    if (group && project && tree && path) {
+      return {
+        type: UrlType.GITLAB_DOT_COM_FILE,
+        group: group,
+        project,
+        branch: tree,
+        filePath: path,
+        url,
+      };
+    }
+  }
+
+  // 7. Default repo view: eg: https://gitlab.com/group/project
+  const repoDefaultViewMatch = pathname.match(GITLAB_DEFAULT_REPO_REGEX);
+  if (repoDefaultViewMatch) {
+    const [, group, project] = repoDefaultViewMatch ?? [];
+    if (group && project) {
+      const customGitRepoUrl = new URL(url);
+      // Without .git on GitLab → Error (not a git repository or unexpected server response)
+      // Ensure the pathname ends with `.git`
+      customGitRepoUrl.pathname = ensureGitExtension(customGitRepoUrl.pathname);
+      return {
+        type: UrlType.GITLAB_DOT_COM,
+        group,
+        project,
+        url: customGitRepoUrl,
+      };
+    }
+  }
+
+  return { type: UrlType.NOT_SUPPORTED, error: "Unsupported GitLab URL", url };
+}
diff --git a/packages/online-editor/src/gitlab/useGitlabClient.ts b/packages/online-editor/src/gitlab/useGitlabClient.ts
new file mode 100644
index 00000000000..8cb579b1025
--- /dev/null
+++ b/packages/online-editor/src/gitlab/useGitlabClient.ts
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { useMemo } from "react";
+import { CorsProxyHeaderKeys } from "@kie-tools/cors-proxy-api";
+import { GitlabClient, GitlabClientApi } from "./GitlabClient";
+import { useAuthProviders } from "../authProviders/AuthProvidersContext";
+import { useEnv } from "../env/hooks/EnvContext";
+import { AuthSession } from "../authSessions/AuthSessionApi";
+
+export function getGitlabClient(args: {
+  appName: string;
+  token?: string;
+  domain?: string;
+  proxyUrl?: string;
+  insecurelyDisableTlsCertificateValidation?: boolean;
+  disableEncoding?: boolean;
+}) {
+  return new GitlabClient({
+    appName: args.appName,
+    token: args.token,
+    domain: args.domain,
+    proxyUrl: args.insecurelyDisableTlsCertificateValidation ? args.proxyUrl : undefined,
+    headers: {
+      ...(args.insecurelyDisableTlsCertificateValidation
+        ? {
+            [CorsProxyHeaderKeys.INSECURELY_DISABLE_TLS_CERTIFICATE_VALIDATION]: Boolean(
+              args.insecurelyDisableTlsCertificateValidation
+            ).toString(),
+          }
+        : {}),
+      // If disableEncoding is true, force proxy/server to skip compression
+      ...(args.disableEncoding
+        ? {
+            [CorsProxyHeaderKeys.DISABLE_ENCODING]: Boolean(args.disableEncoding).toString(),
+          }
+        : {}),
+    },
+  });
+}
+
+export function useGitlabClient(authSession: AuthSession | undefined): GitlabClientApi {
+  const authProviders = useAuthProviders();
+  const { env } = useEnv();
+
+  return useMemo(() => {
+    if (authSession?.type !== "git") {
+      return getGitlabClient({ appName: env.KIE_SANDBOX_APP_NAME });
+    }
+
+    const authProvider = authProviders.find((a) => a.id === authSession.authProviderId);
+    if (authProvider?.type !== "gitlab") {
+      return getGitlabClient({ appName: env.KIE_SANDBOX_APP_NAME });
+    }
+
+    return getGitlabClient({
+      appName: env.KIE_SANDBOX_APP_NAME,
+      token: authSession?.token,
+      domain: authProvider.domain,
+      proxyUrl: env.KIE_SANDBOX_CORS_PROXY_URL,
+      insecurelyDisableTlsCertificateValidation: authProvider.insecurelyDisableTlsCertificateValidation,
+      disableEncoding: authProvider.disableEncoding,
+    });
+  }, [authProviders, authSession, env.KIE_SANDBOX_APP_NAME, env.KIE_SANDBOX_CORS_PROXY_URL]);
+}
diff --git a/packages/online-editor/src/i18n/locales/de.ts b/packages/online-editor/src/i18n/locales/de.ts
index 6f0baf32574..42b3a544985 100644
--- a/packages/online-editor/src/i18n/locales/de.ts
+++ b/packages/online-editor/src/i18n/locales/de.ts
@@ -355,6 +355,31 @@ export const de: OnlineI18n = {
         },
       },
     },
+    gitlab: {
+      header: {
+        title: `${de_common.names.gitlab} ${de_common.names.oauth} ${de_common.terms.token}`,
+        subtitle: `Richten Sie Ihr ${de_common.names.gitlab}-Token ein, damit Sie mit ${de_common.names.gitlab} interagieren können.`,
+      },
+      footer: {
+        createNewToken: "Neues Token generieren",
+        placeHolder: "Fügen Sie hier Ihren Token ein",
+      },
+      body: {
+        learnMore: `Erfahren Sie mehr über ${de_common.names.gitlab}-Token`,
+        note: `Sie sollten ein Token mit der Berechtigung ${"'api' 'read_user' 'read_repository' 'write_repository'"} bereitstellen.`,
+      },
+      validation: {
+        scopes: {
+          helper: "Ihr Token muss die Bereiche 'api' 'read_user' 'read_repository' 'write_repository' enthalten.",
+        },
+      },
+      form: {
+        token: {
+          label: "Persönliches Zugriffstoken",
+          placeHolder: `Fügen Sie Ihr ${de_common.names.gitlab} Token ein.`,
+        },
+      },
+    },
     auth: {
       disclaimer: `Das von Ihnen angegebene Token wird lokal in diesem Browser gespeichert und niemals an Dritte weitergegeben..`,
       error: {
@@ -666,6 +691,21 @@ export const de: OnlineI18n = {
         },
       },
     },
+    gitlab: {
+      repository: `${de_common.names.gitlab} repository`,
+      createRepository: `Erstelle ${de_common.names.gitlab} repository`,
+      description: (workspace: string) =>
+        `Der Inhalt von '${workspace}' wird in das neue ${de_common.names.gitlab} repository übernommen.`,
+      error: {
+        formAlert: (error: string) => `Fehler beim Erstellen des Repositorys ${de_common.names.gitlab}. ${error}`,
+      },
+      form: {
+        select: {
+          label: "Das neue Repository wird unter dem folgenden Scope erstellt",
+          description: `Wählen Sie entweder Ihr Benutzerkonto oder eine ${de_common.names.gitlab} Gruppe.`,
+        },
+      },
+    },
   },
   createGistOrSnippetModal: {
     form: {
@@ -711,6 +751,21 @@ export const de: OnlineI18n = {
         },
       },
     },
+    gitlab: {
+      gistOrSnippet: `${de_common.names.gitlab} Snippet`,
+      create: `Erstelle ${de_common.names.gitlab} Snippet`,
+      description: (workspace: string) =>
+        `Der Inhalt des '${workspace}' wird in dem neuen ${de_common.names.gitlab} Snippet.`,
+      error: {
+        formAlert: (error: string) => `Fehler beim Erstellen von ${de_common.names.gitlab} Snippet. ${error}`,
+      },
+      form: {
+        select: {
+          label: "Wählen Sie einen Arbeitsbereich aus, unter dem das neue Snippet erstellt wird.",
+          description: "Wählen Sie entweder ein persönliches oder ein gemeinsames Projekt aus.",
+        },
+      },
+    },
   },
   loadOrganizationsSelect: {
     bitbucket: {
@@ -721,6 +776,10 @@ export const de: OnlineI18n = {
       user: "GitHub-Benutzer",
       organizations: "GitHub Organisationen",
     },
+    gitlab: {
+      user: `${de_common.names.gitlab} user`,
+      organizations: `${de_common.names.gitlab} Gruppen`,
+    },
   },
   gitStatusIndicatorActions: {
     revert: {
diff --git a/packages/online-editor/src/i18n/locales/en.ts b/packages/online-editor/src/i18n/locales/en.ts
index d738fc479b3..2f6add5d92a 100644
--- a/packages/online-editor/src/i18n/locales/en.ts
+++ b/packages/online-editor/src/i18n/locales/en.ts
@@ -344,6 +344,31 @@ export const en: OnlineI18n = {
         },
       },
     },
+    gitlab: {
+      header: {
+        title: `${en_common.names.gitlab} ${en_common.names.oauth} ${en_common.terms.token}`,
+        subtitle: `Set up your ${en_common.names.gitlab} token so you can interact with ${en_common.names.gitlab}.`,
+      },
+      footer: {
+        createNewToken: "Generate new token",
+        placeHolder: "Paste your token here",
+      },
+      body: {
+        learnMore: `Learn more about ${en_common.names.gitlab} tokens`,
+        note: `You should provide a token with the ${"'api' 'read_user' 'read_repository' 'write_repository'"} permission.`,
+      },
+      validation: {
+        scopes: {
+          helper: `Your token must include the ${"'api' 'read_user' 'read_repository' 'write_repository'"} scopes.`,
+        },
+      },
+      form: {
+        token: {
+          label: "Personal Access Token",
+          placeHolder: `Paste your ${en_common.names.gitlab} token here`,
+        },
+      },
+    },
     auth: {
       disclaimer: `The token you provide is locally stored in this browser and is never shared with anyone.`,
       error: {
@@ -650,6 +675,21 @@ export const en: OnlineI18n = {
         },
       },
     },
+    gitlab: {
+      repository: `${en_common.names.gitlab} repository`,
+      createRepository: `Create ${en_common.names.gitlab} repository`,
+      description: (workspace: string) =>
+        `The contents of '${workspace}' will be all in the new ${en_common.names.gitlab} repository.`,
+      error: {
+        formAlert: (error: string) => `Error creating ${en_common.names.gitlab} repository. ${error}`,
+      },
+      form: {
+        select: {
+          label: "The new repository will be created under the following scope",
+          description: `Pick either your user account or a ${en_common.names.gitlab} group.`,
+        },
+      },
+    },
   },
   createGistOrSnippetModal: {
     form: {
@@ -695,6 +735,21 @@ export const en: OnlineI18n = {
         },
       },
     },
+    gitlab: {
+      gistOrSnippet: `${en_common.names.gitlab} Snippet`,
+      create: `Create ${en_common.names.gitlab} Snippet`,
+      description: (workspace: string) =>
+        `The contents of '${workspace}' will be all in the new ${en_common.names.gitlab} Snippet.`,
+      error: {
+        formAlert: (error: string) => `Error creating ${en_common.names.gitlab} Snippet. ${error}`,
+      },
+      form: {
+        select: {
+          label: "Pick a project under which the new Snippet will be created.",
+          description: "Pick either a personal or shared project.",
+        },
+      },
+    },
   },
   loadOrganizationsSelect: {
     bitbucket: {
@@ -705,6 +760,10 @@ export const en: OnlineI18n = {
       user: "GitHub user",
       organizations: "GitHub organizations",
     },
+    gitlab: {
+      user: `${en_common.names.gitlab} user`,
+      organizations: `${en_common.names.gitlab} groups`,
+    },
   },
   gitStatusIndicatorActions: {
     revert: {
diff --git a/packages/online-editor/src/importFromUrl/AdvancedImportModalContent.tsx b/packages/online-editor/src/importFromUrl/AdvancedImportModalContent.tsx
index def2d146db7..a9e8c73bad7 100644
--- a/packages/online-editor/src/importFromUrl/AdvancedImportModalContent.tsx
+++ b/packages/online-editor/src/importFromUrl/AdvancedImportModalContent.tsx
@@ -171,7 +171,7 @@ export const AdvancedImportModal = React.forwardRef<AdvancedImportModalRef, Adva
                   aria-label="Disable TLS Certificate Validation"
                   tabIndex={4}
                   isChecked={props.insecurelyDisableTlsCertificateValidation}
-                  onChange={(_event, val) => props.setInsecurelyDisableTlsCertificateValidation}
+                  onChange={(_event, val) => props.setInsecurelyDisableTlsCertificateValidation(val)}
                 />
               </FormGroup>
               <FormGroup fieldId="url" label="URL" isRequired={true}>
@@ -184,16 +184,12 @@ export const AdvancedImportModal = React.forwardRef<AdvancedImportModalRef, Adva
                   onChange={(_event, value) => props.setUrl(value)}
                 />
                 <HelperText>
-                  {props.validation.helperTextInvalid === "error" ? (
+                  {props.validation.option === "error" ? (
                     <HelperTextItem variant="error" icon={<ExclamationCircleIcon />}>
-                      {props.validation.option !== ValidatedOptions.success ? (
-                        props.validation.helperText
-                      ) : (
-                        <FormHelperText />
-                      )}
+                      {props.validation.helperTextInvalid}
                     </HelperTextItem>
                   ) : (
-                    <HelperTextItem icon={props.validation.option}></HelperTextItem>
+                    props.validation.option !== "success" && props.validation.helperText
                   )}
                 </HelperText>
               </FormGroup>
@@ -230,11 +226,7 @@ export const AdvancedImportModal = React.forwardRef<AdvancedImportModalRef, Adva
                       </SelectGroup>
                     ))}
                 </Select>
-                <HelperText>
-                  <HelperTextItem variant="error" icon={ValidatedOptions.default}>
-                    {<FormHelperText>Loading...</FormHelperText>}
-                  </HelperTextItem>
-                </HelperText>
+                <HelperText>{props.validation.option !== "success" && props.validation.helperText}</HelperText>
               </FormGroup>
             </Form>
             <br />
diff --git a/packages/online-editor/src/importFromUrl/ImportFromUrlHomePageCard.tsx b/packages/online-editor/src/importFromUrl/ImportFromUrlHomePageCard.tsx
index 9d96d679901..a012eb7acea 100644
--- a/packages/online-editor/src/importFromUrl/ImportFromUrlHomePageCard.tsx
+++ b/packages/online-editor/src/importFromUrl/ImportFromUrlHomePageCard.tsx
@@ -48,6 +48,7 @@ export function ImportFromUrlCard() {
   const [authSessionId, setAuthSessionId] = useState<string | undefined>(AUTH_SESSION_NONE.id);
   const [url, setUrl] = useState("");
   const [insecurelyDisableTlsCertificateValidation, setInsecurelyDisableTlsCertificateValidation] = useState(false);
+  const [disableEncoding, setDisableEncoding] = useState(false);
   const [gitRefName, setGitRef] = useState("");
 
   const advancedImportModalRef = useRef<AdvancedImportModalRef>(null);
@@ -56,13 +57,19 @@ export function ImportFromUrlCard() {
 
   const importableUrl = useImportableUrl(url);
 
-  const clonableUrl = useClonableUrl(url, authInfo, gitRefName, insecurelyDisableTlsCertificateValidation);
+  const clonableUrl = useClonableUrl(
+    url,
+    authInfo,
+    gitRefName,
+    insecurelyDisableTlsCertificateValidation,
+    disableEncoding
+  );
 
   // Select authSession based on the importableUrl domain (begin)
   const authProviders = useAuthProviders();
   const { authSessions, authSessionStatus } = useAuthSessions();
 
-  const updateInsecurelyDisableTlsCertificateValidation = useCallback(
+  const updateInsecurelyDisableTlsCertificateValidationAndDisableEncoding = useCallback(
     (newAuthSession: AuthSession) => {
       if (newAuthSession?.type === "git") {
         const localAuthProvider = authProviders.find((provider) => provider.id === newAuthSession.authProviderId);
@@ -70,6 +77,7 @@ export function ImportFromUrlCard() {
           setInsecurelyDisableTlsCertificateValidation(
             localAuthProvider.insecurelyDisableTlsCertificateValidation ?? false
           );
+          setDisableEncoding(localAuthProvider.disableEncoding ?? false);
         }
       }
     },
@@ -85,8 +93,14 @@ export function ImportFromUrlCard() {
       urlDomain,
     });
     setAuthSessionId(compatible[0]!.id);
-    updateInsecurelyDisableTlsCertificateValidation(compatible[0]);
-  }, [authProviders, authSessionStatus, authSessions, importableUrl, updateInsecurelyDisableTlsCertificateValidation]);
+    updateInsecurelyDisableTlsCertificateValidationAndDisableEncoding(compatible[0]);
+  }, [
+    authProviders,
+    authSessionStatus,
+    authSessions,
+    importableUrl,
+    updateInsecurelyDisableTlsCertificateValidationAndDisableEncoding,
+  ]);
   // Select authSession based on the importableUrl domain (end)
 
   useEffect(() => {
@@ -94,8 +108,8 @@ export function ImportFromUrlCard() {
   }, [clonableUrl.selectedGitRefName]);
 
   useEffect(() => {
-    authSession && updateInsecurelyDisableTlsCertificateValidation(authSession);
-  }, [authSession, updateInsecurelyDisableTlsCertificateValidation]);
+    authSession && updateInsecurelyDisableTlsCertificateValidationAndDisableEncoding(authSession);
+  }, [authSession, updateInsecurelyDisableTlsCertificateValidationAndDisableEncoding]);
 
   const validation = useImportableUrlValidation(authSession, url, gitRefName, clonableUrl, advancedImportModalRef);
 
@@ -119,10 +133,20 @@ export function ImportFromUrlCard() {
           branch: gitRefName,
           authSessionId,
           insecurelyDisableTlsCertificateValidation: insecurelyDisableTlsCertificateValidation.toString(),
+          disableEncoding: disableEncoding.toString(),
         }),
       });
     },
-    [authSessionId, gitRefName, navigate, isValid, routes.import, url, insecurelyDisableTlsCertificateValidation]
+    [
+      authSessionId,
+      gitRefName,
+      navigate,
+      isValid,
+      routes.import,
+      url,
+      insecurelyDisableTlsCertificateValidation,
+      disableEncoding,
+    ]
   );
 
   const buttonLabel = useMemo(() => {
@@ -168,7 +192,7 @@ export function ImportFromUrlCard() {
         <CardBody>
           <TextContent>
             <Text component={TextVariants.p}>
-              Import a Git repository, a GitHub Gist, Bitbucket Snippet, or any other file URL.
+              Import a Git repository, a GitHub Gist, Bitbucket Snippet, GitLab Snippet or any other file URL.
             </Text>
           </TextContent>
           <br />
diff --git a/packages/online-editor/src/importFromUrl/ImportSingleFileFromUrlForm.tsx b/packages/online-editor/src/importFromUrl/ImportSingleFileFromUrlForm.tsx
index 13e8cb7f94f..5d5b1583841 100644
--- a/packages/online-editor/src/importFromUrl/ImportSingleFileFromUrlForm.tsx
+++ b/packages/online-editor/src/importFromUrl/ImportSingleFileFromUrlForm.tsx
@@ -100,7 +100,7 @@ export function ImportSingleFileFromUrlForm(props: {
           isRequired={true}
           placeholder={"File URL"}
           value={props.url}
-          onChange={(_event, val) => props.setUrl}
+          onChange={(_event, val) => props.setUrl(val)}
         />
         {validatedOption === "error" ? (
           <FormHelperText>
diff --git a/packages/online-editor/src/importFromUrl/ImportableUrlHooks.tsx b/packages/online-editor/src/importFromUrl/ImportableUrlHooks.tsx
index 8b07001c383..3d00ec2a06c 100644
--- a/packages/online-editor/src/importFromUrl/ImportableUrlHooks.tsx
+++ b/packages/online-editor/src/importFromUrl/ImportableUrlHooks.tsx
@@ -28,9 +28,9 @@ import * as React from "react";
 import { useCallback, useMemo } from "react";
 import { matchPath } from "react-router-dom";
 import { AuthProviderIcon } from "../authProviders/AuthProviderIcon";
-import { useAuthProvider } from "../authProviders/AuthProvidersContext";
+import { useAuthProvider, useAuthProviders } from "../authProviders/AuthProvidersContext";
 import { AuthSession, AUTH_SESSION_NONE } from "../authSessions/AuthSessionApi";
-import { AuthInfo } from "../authSessions/AuthSessionsContext";
+import { AuthInfo, useAuthSessions } from "../authSessions/AuthSessionsContext";
 import { useEditorEnvelopeLocator } from "../envelopeLocator/hooks/EditorEnvelopeLocatorContext";
 import { AdvancedImportModalRef } from "./AdvancedImportModalContent";
 import { getGitRefName, getGitRefType } from "../gitRefs/GitRefs";
@@ -38,8 +38,11 @@ import { PromiseStateStatus, useLivePromiseState } from "@kie-tools-core/react-h
 import { useWorkspaces } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
 import { GitServerRef } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/GitServerRef";
 import { GitRefTypeIcon } from "../gitRefs/GitRefTypeIcon";
+import { parseGitLabUrl } from "../gitlab/ParseGitLabUrl";
 import { Icon } from "@patternfly/react-core/dist/js/components/Icon";
 import { Spinner } from "@patternfly/react-core/dist/js/components/Spinner";
+import { getCompatibleAuthSessionWithUrlDomain } from "../authSessions/CompatibleAuthSessions";
+import { AuthProviderType } from "../authProviders/AuthProvidersApi";
 
 export enum UrlType {
   //git
@@ -48,12 +51,16 @@ export enum UrlType {
   GIST_DOT_GITHUB_DOT_COM,
   BITBUCKET_DOT_ORG,
   BITBUCKET_DOT_ORG_SNIPPET,
+  GITLAB_DOT_COM,
+  GITLAB_DOT_COM_SNIPPET,
 
   //single file
   GIST_DOT_GITHUB_DOT_COM_FILE,
   GITHUB_DOT_COM_FILE,
   BITBUCKET_DOT_ORG_FILE,
   BITBUCKET_DOT_ORG_SNIPPET_FILE,
+  GITLAB_DOT_COM_FILE,
+  GITLAB_DOT_COM_SNIPPET_FILE,
   FILE,
 
   //other
@@ -68,7 +75,9 @@ export function isCertainlyGit(urlType: UrlType): boolean {
     urlType === UrlType.GITHUB_DOT_COM ||
     urlType === UrlType.GIST_DOT_GITHUB_DOT_COM ||
     urlType === UrlType.BITBUCKET_DOT_ORG ||
-    urlType === UrlType.BITBUCKET_DOT_ORG_SNIPPET
+    urlType === UrlType.BITBUCKET_DOT_ORG_SNIPPET ||
+    urlType === UrlType.GITLAB_DOT_COM ||
+    urlType === UrlType.GITLAB_DOT_COM_SNIPPET
   );
 }
 
@@ -82,7 +91,9 @@ export function isSingleFile(urlType: UrlType) {
     urlType === UrlType.GIST_DOT_GITHUB_DOT_COM_FILE ||
     urlType === UrlType.GITHUB_DOT_COM_FILE ||
     urlType === UrlType.BITBUCKET_DOT_ORG_FILE ||
-    urlType === UrlType.BITBUCKET_DOT_ORG_SNIPPET_FILE
+    urlType === UrlType.BITBUCKET_DOT_ORG_SNIPPET_FILE ||
+    urlType === UrlType.GITLAB_DOT_COM_FILE ||
+    urlType === UrlType.GITLAB_DOT_COM_SNIPPET_FILE
   );
 }
 
@@ -157,6 +168,42 @@ export type ImportableUrl =
       org: string;
       filename: string;
     }
+  | {
+      type: UrlType.GITLAB_DOT_COM;
+      project: string;
+      url: URL;
+      group?: string;
+      branch?: string;
+      error?: undefined;
+    }
+  | {
+      type: UrlType.GITLAB_DOT_COM_FILE;
+      error?: undefined;
+      url: URL;
+      group?: string;
+      project: string;
+      branch: string;
+      filePath: string;
+    }
+  | {
+      type: UrlType.GITLAB_DOT_COM_SNIPPET;
+      url: URL;
+      snippetId: string;
+      group?: string;
+      project?: string;
+      branch?: string;
+      error?: undefined;
+    }
+  | {
+      type: UrlType.GITLAB_DOT_COM_SNIPPET_FILE;
+      url: URL;
+      snippetId: string;
+      error?: undefined;
+      group?: string;
+      project?: string;
+      branch?: string;
+      filePath?: string;
+    }
   | {
       type: UrlType.NOT_SUPPORTED;
       error: string;
@@ -175,6 +222,8 @@ export type ImportableUrl =
 
 export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]): ImportableUrl {
   const editorEnvelopeLocator = useEditorEnvelopeLocator();
+  const { authSessions, authSessionStatus } = useAuthSessions();
+  const authProviders = useAuthProviders();
 
   const ifAllowed = useCallback(
     (url: ImportableUrl): ImportableUrl => {
@@ -187,6 +236,40 @@ export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]
     [allowedUrlTypes]
   );
 
+  const isGitRemoteDomainAllowed = useCallback(
+    (
+      url: URL,
+      hostname: string | string[],
+      authProvider: AuthProviderType.bitbucket | AuthProviderType.github | AuthProviderType.gitlab
+    ) => {
+      const hostnames = Array.isArray(hostname) ? hostname : [hostname];
+      // allow if exact match
+      if (hostnames.includes(url.host)) {
+        return true;
+      }
+      // Step 1: Determine which auth sessions are compatible with the given URL domain
+      const { compatible } = getCompatibleAuthSessionWithUrlDomain({
+        authProviders,
+        authSessions,
+        authSessionStatus,
+        urlDomain: url.host,
+      });
+      // Step 2: Find the first compatible auth provider (if any)
+      const selectedAuthProvider = authProviders?.find(
+        ({ id }) => compatible?.[0]?.type !== "none" && id === compatible?.[0]?.authProviderId
+      );
+      if (!selectedAuthProvider || selectedAuthProvider.type !== AuthProviderType[authProvider]) {
+        return false;
+      }
+      // Step 3: Validate whether the hostname is allowed for the selected provider
+      return (
+        selectedAuthProvider?.domain === url.host || // match primary domain
+        selectedAuthProvider?.supportedGitRemoteDomains?.some((supportedDomain) => supportedDomain === url.host) // match against supported domains
+      );
+    },
+    [authProviders, authSessionStatus, authSessions]
+  );
+
   return useMemo(() => {
     if (!urlString) {
       return { type: UrlType.INVALID, error: "Empty URL" };
@@ -231,7 +314,7 @@ export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]
 
       const gitHubFileMatch = matchPath(
         {
-          path: "/:org/:repo/blob/:tree/:path*",
+          path: "/:org/:repo/blob/:tree/*",
           end: true,
           caseSensitive: true,
         },
@@ -243,7 +326,7 @@ export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]
         gitHubFileMatch.params.org &&
         gitHubFileMatch.params.repo &&
         gitHubFileMatch.params.tree &&
-        gitHubFileMatch.params["path*"]
+        gitHubFileMatch.params["*"]
       ) {
         return ifAllowed({
           type: UrlType.GITHUB_DOT_COM_FILE,
@@ -251,7 +334,7 @@ export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]
           org: gitHubFileMatch.params.org,
           repo: gitHubFileMatch.params.repo,
           branch: gitHubFileMatch.params.tree,
-          filePath: gitHubFileMatch.params["path*"],
+          filePath: gitHubFileMatch.params["*"],
         });
       }
 
@@ -290,7 +373,7 @@ export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]
 
       const bitbucketFileMatch = matchPath(
         {
-          path: "/:org/:repo/src/:tree/:path*",
+          path: "/:org/:repo/src/:tree/*",
           end: true,
           caseSensitive: true,
         },
@@ -302,7 +385,7 @@ export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]
         bitbucketFileMatch.params.org &&
         bitbucketFileMatch.params.repo &&
         bitbucketFileMatch.params.tree &&
-        bitbucketFileMatch.params["path*"]
+        bitbucketFileMatch.params["*"]
       ) {
         return ifAllowed({
           type: UrlType.BITBUCKET_DOT_ORG_FILE,
@@ -310,7 +393,7 @@ export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]
           org: bitbucketFileMatch.params.org,
           repo: bitbucketFileMatch.params.repo,
           branch: bitbucketFileMatch.params.tree,
-          filePath: bitbucketFileMatch.params["path*"],
+          filePath: bitbucketFileMatch.params["*"],
         });
       }
 
@@ -382,7 +465,7 @@ export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]
     if (url.host === "raw.githubusercontent.com") {
       const gitHubRawFileMatch = matchPath(
         {
-          path: "/:org/:repo/refs/heads/:tree/:path*",
+          path: "/:org/:repo/refs/heads/:tree/*",
           end: true,
           caseSensitive: true,
         },
@@ -394,7 +477,7 @@ export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]
         gitHubRawFileMatch.params.org &&
         gitHubRawFileMatch.params.repo &&
         gitHubRawFileMatch.params.tree &&
-        gitHubRawFileMatch.params["path*"]
+        gitHubRawFileMatch.params["*"]
       ) {
         return ifAllowed({
           type: UrlType.GITHUB_DOT_COM_FILE,
@@ -402,7 +485,7 @@ export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]
           org: gitHubRawFileMatch.params.org,
           repo: gitHubRawFileMatch.params.repo,
           branch: gitHubRawFileMatch.params.tree,
-          filePath: gitHubRawFileMatch.params["path*"],
+          filePath: gitHubRawFileMatch.params["*"],
         });
       }
 
@@ -466,6 +549,12 @@ export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]
       });
     }
 
+    // Gitlab
+    if (isGitRemoteDomainAllowed(url, "gitlab.com", AuthProviderType.gitlab)) {
+      const gitlabImportUrl = parseGitLabUrl(url);
+      return ifAllowed(gitlabImportUrl);
+    }
+
     const extension = extname(url.pathname).replace(".", "");
     if (extension) {
       if (extension === "git") {
@@ -480,21 +569,23 @@ export function useImportableUrl(urlString?: string, allowedUrlTypes?: UrlType[]
     }
 
     return { type: UrlType.UNKNOWN, url };
-  }, [urlString, ifAllowed, editorEnvelopeLocator]);
+  }, [urlString, ifAllowed, editorEnvelopeLocator, isGitRemoteDomainAllowed]);
 }
 
 export function useClonableUrl(
   url: string | undefined,
   authInfo: AuthInfo | undefined,
   gitRefName: string | undefined,
-  insecurelyDisableTlsCertificateValidation?: boolean
+  insecurelyDisableTlsCertificateValidation?: boolean,
+  disableEncoding?: boolean
 ) {
   const importableUrl = useImportableUrl(url);
 
   const gitServerRefsPromise = useGitServerRefs(
     isPotentiallyGit(importableUrl.type) ? importableUrl.url : undefined,
     authInfo,
-    insecurelyDisableTlsCertificateValidation
+    insecurelyDisableTlsCertificateValidation,
+    disableEncoding
   );
 
   const gitRefNameFromUrl = useMemo(() => {
@@ -560,7 +651,8 @@ export function useClonableUrl(
 export function useGitServerRefs(
   url: URL | undefined,
   authInfo: AuthInfo | undefined,
-  insecurelyDisableTlsCertificateValidation?: boolean
+  insecurelyDisableTlsCertificateValidation?: boolean,
+  disableEncoding?: boolean
 ) {
   const workspaces = useWorkspaces();
 
@@ -574,6 +666,7 @@ export function useGitServerRefs(
           url: url.toString(),
           authInfo,
           insecurelyDisableTlsCertificateValidation,
+          disableEncoding,
         });
 
         const headRef = refs.filter((f) => f.ref === "HEAD").pop()!.target!;
@@ -582,7 +675,7 @@ export function useGitServerRefs(
 
         return { refs, defaultBranch, headRef };
       };
-    }, [authInfo, url, workspaces, insecurelyDisableTlsCertificateValidation])
+    }, [authInfo, url, workspaces, insecurelyDisableTlsCertificateValidation, disableEncoding])
   );
 
   return gitServerRefsPromise;
diff --git a/packages/online-editor/src/importFromUrl/NewWorkspaceFromUrlPage.tsx b/packages/online-editor/src/importFromUrl/NewWorkspaceFromUrlPage.tsx
index 107f51ae56c..3db98eea15b 100644
--- a/packages/online-editor/src/importFromUrl/NewWorkspaceFromUrlPage.tsx
+++ b/packages/online-editor/src/importFromUrl/NewWorkspaceFromUrlPage.tsx
@@ -54,6 +54,7 @@ import { PromiseStateStatus } from "@kie-tools-core/react-hooks/dist/PromiseStat
 import { AUTH_SESSION_NONE } from "../authSessions/AuthSessionApi";
 import { useBitbucketClient } from "../bitbucket/Hooks";
 import { AuthProviderGroup } from "../authProviders/AuthProvidersApi";
+import { useGitlabClient } from "../gitlab/useGitlabClient";
 
 export function NewWorkspaceFromUrlPage() {
   const workspaces = useWorkspaces();
@@ -71,6 +72,7 @@ export function NewWorkspaceFromUrlPage() {
   const queryParamInsecurelyDisableTlsCertificateValidation = useQueryParam(
     QueryParams.INSECURELY_DISABLE_TLS_CERTIFICATE_VALIDATION
   );
+  const queryParamDisableEncodingValidation = useQueryParam(QueryParams.DISABLE_ENCODING);
   const queryParamConfirm = useQueryParam(QueryParams.CONFIRM);
 
   const authProviders = useAuthProviders();
@@ -86,12 +88,20 @@ export function NewWorkspaceFromUrlPage() {
       : false;
   }, [queryParamInsecurelyDisableTlsCertificateValidation, authProvider]);
 
+  const disableEncodingValidation = useMemo(() => {
+    if (typeof queryParamDisableEncodingValidation === "string") {
+      return queryParamDisableEncodingValidation === "true";
+    }
+    return authProvider?.group === AuthProviderGroup.GIT ? authProvider.disableEncoding : false;
+  }, [queryParamDisableEncodingValidation, authProvider]);
+
   const importableUrl = useImportableUrl(queryParamUrl);
   const clonableUrlObject = useClonableUrl(
     queryParamUrl,
     authInfo,
     queryParamBranch,
-    insecurelyDisableTlsCertificateValidation
+    insecurelyDisableTlsCertificateValidation,
+    disableEncodingValidation
   );
   const { clonableUrl, selectedGitRefName, gitServerRefsPromise } = clonableUrlObject;
 
@@ -309,10 +319,16 @@ export function NewWorkspaceFromUrlPage() {
 
   const gitHubClient = useGitHubClient(authSession);
   const bitbucketClient = useBitbucketClient(authSession);
+  const gitlabClient = useGitlabClient(authSession);
 
   const doImportAsSingleFile = useCallback(
     async (importableUrl: ImportableUrl) => {
-      const singleFileContent = await fetchSingleFileContent(importableUrl, gitHubClient, bitbucketClient);
+      const singleFileContent = await fetchSingleFileContent(
+        importableUrl,
+        gitHubClient,
+        bitbucketClient,
+        gitlabClient
+      );
 
       if (singleFileContent.error) {
         setImportingError(singleFileContent.error);
@@ -324,7 +340,7 @@ export function NewWorkspaceFromUrlPage() {
         fileContents: encoder.encode(singleFileContent.content!),
       });
     },
-    [bitbucketClient, createWorkspaceForFile, gitHubClient]
+    [bitbucketClient, createWorkspaceForFile, gitHubClient, gitlabClient]
   );
 
   const doImport = useCallback(async () => {
@@ -354,6 +370,7 @@ export function NewWorkspaceFromUrlPage() {
             authInfo,
             gitAuthSessionId: queryParamAuthSessionId,
             insecurelyDisableTlsCertificateValidation,
+            disableEncoding: disableEncodingValidation,
           });
         } else {
           await doImportAsSingleFile(importableUrl);
@@ -364,6 +381,7 @@ export function NewWorkspaceFromUrlPage() {
       else if (
         importableUrl.type === UrlType.GITHUB_DOT_COM ||
         importableUrl.type === UrlType.BITBUCKET_DOT_ORG ||
+        importableUrl.type === UrlType.GITLAB_DOT_COM ||
         importableUrl.type === UrlType.GIT
       ) {
         if (gitServerRefsPromise.data?.defaultBranch) {
@@ -377,6 +395,7 @@ export function NewWorkspaceFromUrlPage() {
             gitConfig,
             authInfo,
             insecurelyDisableTlsCertificateValidation,
+            disableEncoding: disableEncodingValidation,
           });
         } else {
           setImportingError(`Can't clone. ${gitServerRefsPromise.error}`);
@@ -399,6 +418,7 @@ export function NewWorkspaceFromUrlPage() {
             gitConfig,
             authInfo,
             insecurelyDisableTlsCertificateValidation,
+            disableEncoding: disableEncodingValidation,
           });
         } else {
           setImportingError(`Can't clone. ${gitServerRefsPromise.error}`);
@@ -407,12 +427,18 @@ export function NewWorkspaceFromUrlPage() {
       }
 
       // snippet
-      else if (importableUrl.type === UrlType.BITBUCKET_DOT_ORG_SNIPPET) {
+      else if (
+        importableUrl.type === UrlType.BITBUCKET_DOT_ORG_SNIPPET ||
+        importableUrl.type === UrlType.GITLAB_DOT_COM_SNIPPET
+      ) {
         importableUrl.url.hash = "";
         if (gitServerRefsPromise.data?.defaultBranch) {
           await cloneGitRepository({
             origin: {
-              kind: WorkspaceKind.BITBUCKET_SNIPPET,
+              kind:
+                importableUrl.type === UrlType.BITBUCKET_DOT_ORG_SNIPPET
+                  ? WorkspaceKind.BITBUCKET_SNIPPET
+                  : WorkspaceKind.GITLAB_SNIPPET,
               url: importableUrl.url.toString(),
               branch: queryParamBranch ?? selectedGitRefName ?? gitServerRefsPromise.data.defaultBranch,
             },
@@ -420,6 +446,7 @@ export function NewWorkspaceFromUrlPage() {
             gitConfig,
             authInfo,
             insecurelyDisableTlsCertificateValidation,
+            disableEncoding: disableEncodingValidation,
           });
         } else {
           setImportingError(`Can't clone. ${gitServerRefsPromise.error}`);
@@ -453,6 +480,7 @@ export function NewWorkspaceFromUrlPage() {
     doImportAsSingleFile,
     queryParamBranch,
     insecurelyDisableTlsCertificateValidation,
+    disableEncodingValidation,
   ]);
 
   useEffect(() => {
diff --git a/packages/online-editor/src/importFromUrl/fetchSingleFileContent.ts b/packages/online-editor/src/importFromUrl/fetchSingleFileContent.ts
index 3fd104a71ef..94c998fe159 100644
--- a/packages/online-editor/src/importFromUrl/fetchSingleFileContent.ts
+++ b/packages/online-editor/src/importFromUrl/fetchSingleFileContent.ts
@@ -20,11 +20,13 @@
 import { Octokit } from "@octokit/rest";
 import { BitbucketClientApi } from "../bitbucket/Hooks";
 import { ImportableUrl, UrlType } from "./ImportableUrlHooks";
+import { GitlabClientApi } from "../gitlab/GitlabClient";
 
 export async function fetchSingleFileContent(
   importableUrl: ImportableUrl,
   gitHubClient: Octokit,
-  bitbucketClient: BitbucketClientApi
+  bitbucketClient: BitbucketClientApi,
+  gitlabClient: GitlabClientApi
 ): Promise<{ rawUrl?: URL; content?: string; error?: string }> {
   let rawUrl = importableUrl.url as URL;
   if (importableUrl.type === UrlType.GITHUB_DOT_COM_FILE) {
@@ -90,6 +92,40 @@ export async function fetchSingleFileContent(
     }
     rawUrl = new URL(links.self.href);
   }
+  if (importableUrl.type === UrlType.GITLAB_DOT_COM_FILE) {
+    const repoResponse = await gitlabClient.getRepositoryContents({
+      group: importableUrl.group,
+      project: importableUrl.project,
+      ref: importableUrl.branch,
+      path: decodeURIComponent(importableUrl.filePath),
+    });
+
+    if (!repoResponse.ok) {
+      throw new Error(`Couldn't get Gitlab repository contents: ${repoResponse.status} ${repoResponse.statusText}`);
+    }
+    const content = await repoResponse?.text();
+    if (!content) {
+      throw new Error(`Unexpected contents of Gitlab response`);
+    }
+    return { content, rawUrl: new URL(importableUrl?.url), error: undefined };
+  }
+  if (importableUrl.type === UrlType.GITLAB_DOT_COM_SNIPPET_FILE) {
+    const snippetResponse = await gitlabClient.getSnippetFileRaw({
+      group: importableUrl.group,
+      filePath: decodeURIComponent(importableUrl.filePath!),
+      snippetId: importableUrl.snippetId,
+      branch: importableUrl?.branch,
+      project: importableUrl?.project,
+    });
+    if (!snippetResponse.ok) {
+      throw new Error(`Couldn't get Gitlab snippet contents: ${snippetResponse.status} ${snippetResponse.statusText}`);
+    }
+    const content = await snippetResponse?.text();
+    if (!content) {
+      throw new Error(`Unexpected contents of Gitlab response`);
+    }
+    return { content, rawUrl: new URL(importableUrl?.url), error: undefined };
+  }
 
   const response = await fetch(rawUrl.toString());
   if (!response.ok) {
diff --git a/packages/online-editor/src/navigation/Routes.ts b/packages/online-editor/src/navigation/Routes.ts
index 2bf260c5392..23b3fa48629 100644
--- a/packages/online-editor/src/navigation/Routes.ts
+++ b/packages/online-editor/src/navigation/Routes.ts
@@ -26,6 +26,7 @@ export enum QueryParams {
   EXPAND = "expand",
   AUTH_SESSION_ID = "authSessionId",
   INSECURELY_DISABLE_TLS_CERTIFICATE_VALIDATION = "insecurelyDisableTlsCertificateValidation",
+  DISABLE_ENCODING = "disableEncoding",
   CONFIRM = "confirm",
 }
 
@@ -141,6 +142,7 @@ export const routes = {
       | QueryParams.BRANCH
       | QueryParams.AUTH_SESSION_ID
       | QueryParams.INSECURELY_DISABLE_TLS_CERTIFICATE_VALIDATION
+      | QueryParams.DISABLE_ENCODING
       | QueryParams.CONFIRM;
   }>(() => `/import`),
 
diff --git a/packages/online-editor/src/workspace/components/WorkspaceLabel.tsx b/packages/online-editor/src/workspace/components/WorkspaceLabel.tsx
index c292188709c..693d489a07c 100644
--- a/packages/online-editor/src/workspace/components/WorkspaceLabel.tsx
+++ b/packages/online-editor/src/workspace/components/WorkspaceLabel.tsx
@@ -139,6 +139,19 @@ export function WorkspaceLabel(props: { descriptor?: WorkspaceDescriptor }) {
             </Tooltip>
           </FlexItem>
         ),
+        GITLAB_SNIPPET: (
+          <FlexItem>
+            <Tooltip
+              content={`'${props.descriptor?.name}' is linked to a Gitlab Snippet. ${props.descriptor?.origin.url}`}
+              position={"right"}
+            >
+              <Label>
+                <GitlabIcon />
+                &nbsp;&nbsp;Snippet
+              </Label>
+            </Tooltip>
+          </FlexItem>
+        ),
         LOCAL: (
           <FlexItem>
             <Tooltip
diff --git a/packages/workspaces-git-fs/src/context/WorkspacesContext.tsx b/packages/workspaces-git-fs/src/context/WorkspacesContext.tsx
index ac89dc98c72..26a8071b2a4 100644
--- a/packages/workspaces-git-fs/src/context/WorkspacesContext.tsx
+++ b/packages/workspaces-git-fs/src/context/WorkspacesContext.tsx
@@ -26,7 +26,14 @@ import {
 import * as React from "react";
 import { createContext, useContext } from "react";
 import { WorkspaceDescriptor } from "../worker/api/WorkspaceDescriptor";
-import { BitbucketOrigin, GistOrigin, GitHubOrigin, SnippetOrigin } from "../worker/api/WorkspaceOrigin";
+import {
+  BitbucketOrigin,
+  GistOrigin,
+  GitHubOrigin,
+  GitlabOrigin,
+  GitlabSnippetOrigin,
+  BitbucketSnippetOrigin,
+} from "../worker/api/WorkspaceOrigin";
 import { LocalFile } from "../worker/api/LocalFile";
 import { decoder } from "../encoderdecoder/EncoderDecoder";
 import { parseWorkspaceFileRelativePath } from "../relativePath/WorkspaceFileRelativePathParser";
@@ -103,7 +110,7 @@ export interface WorkspacesContextType {
   }>;
 
   createWorkspaceFromGitRepository: (args: {
-    origin: GistOrigin | GitHubOrigin | BitbucketOrigin | SnippetOrigin;
+    origin: GistOrigin | GitHubOrigin | BitbucketOrigin | BitbucketSnippetOrigin | GitlabOrigin | GitlabSnippetOrigin;
     gitConfig?: { email: string; name: string };
     gitAuthSessionId: string | undefined;
     authInfo?: {
@@ -111,6 +118,7 @@ export interface WorkspacesContextType {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }) => Promise<{ workspace: WorkspaceDescriptor; suggestedFirstFile?: WorkspaceFile }>;
 
   pull(args: {
@@ -121,6 +129,7 @@ export interface WorkspacesContextType {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void>;
 
   push(args: {
@@ -134,6 +143,7 @@ export interface WorkspacesContextType {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void>;
 
   deleteBranch(args: { workspaceId: string; ref: string }): Promise<void>;
@@ -157,6 +167,7 @@ export interface WorkspacesContextType {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<GitServerRef[]>;
 
   hasLocalChanges(args: { workspaceId: string }): Promise<boolean>;
@@ -196,6 +207,7 @@ export interface WorkspacesContextType {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<FetchResult>;
 
   // storage
@@ -257,6 +269,7 @@ export interface WorkspacesContextType {
     remoteUrl: URL;
     branch?: string;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void>;
 
   initGistOnWorkspace(args: {
@@ -264,6 +277,7 @@ export interface WorkspacesContextType {
     remoteUrl: URL;
     branch: string;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void>;
 
   initSnippetOnWorkspace(args: {
@@ -271,12 +285,22 @@ export interface WorkspacesContextType {
     remoteUrl: URL;
     branch: string;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
+  }): Promise<void>;
+
+  initGilabSnippetOnWorkspace(args: {
+    workspaceId: string;
+    remoteUrl: URL;
+    branch: string;
+    insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void>;
 
   changeGitAuthSessionId(args: {
     workspaceId: string;
     gitAuthSessionId: string | undefined;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void>;
 
   initLocalOnWorkspace(args: { workspaceId: string }): Promise<void>;
diff --git a/packages/workspaces-git-fs/src/context/WorkspacesContextProvider.tsx b/packages/workspaces-git-fs/src/context/WorkspacesContextProvider.tsx
index 73b8e2078b6..84f1de1d3a0 100644
--- a/packages/workspaces-git-fs/src/context/WorkspacesContextProvider.tsx
+++ b/packages/workspaces-git-fs/src/context/WorkspacesContextProvider.tsx
@@ -22,7 +22,14 @@ import { useCallback, useMemo } from "react";
 import { ResourceContentOptions } from "@kie-tools-core/workspace/dist/api";
 import { WorkspaceFile, WorkspacesContext } from "./WorkspacesContext";
 import { LocalFile } from "../worker/api/LocalFile";
-import { BitbucketOrigin, GistOrigin, GitHubOrigin, SnippetOrigin } from "../worker/api/WorkspaceOrigin";
+import {
+  BitbucketOrigin,
+  BitbucketSnippetOrigin,
+  GistOrigin,
+  GitHubOrigin,
+  GitlabOrigin,
+  GitlabSnippetOrigin,
+} from "../worker/api/WorkspaceOrigin";
 import { WorkspaceWorkerFileDescriptor } from "../worker/api/WorkspaceWorkerFileDescriptor";
 import { WorkspacesSharedWorker } from "../worker/WorkspacesSharedWorker";
 
@@ -105,6 +112,7 @@ export function WorkspacesContextProvider(props: Props) {
       gitConfig?: { name: string; email: string };
       authInfo?: { username: string; password: string };
       insecurelyDisableTlsCertificateValidation?: boolean;
+      disableEncoding?: boolean;
     }) =>
       workspacesSharedWorker.withBus((workspacesWorkerBus) =>
         workspacesWorkerBus.clientApi.requests.kieSandboxWorkspacesGit_pull(args)
@@ -124,6 +132,7 @@ export function WorkspacesContextProvider(props: Props) {
         password: string;
       };
       insecurelyDisableTlsCertificateValidation?: boolean;
+      disableEncoding?: boolean;
     }) =>
       workspacesSharedWorker.withBus((workspacesWorkerBus) => {
         return workspacesWorkerBus.clientApi.requests.kieSandboxWorkspacesGit_push(args);
@@ -170,6 +179,7 @@ export function WorkspacesContextProvider(props: Props) {
       ref: string;
       authInfo?: { username: string; password: string };
       insecurelyDisableTlsCertificateValidation?: boolean;
+      disableEncoding?: boolean;
     }) =>
       workspacesSharedWorker.withBus((workspacesWorkerBus) =>
         workspacesWorkerBus.clientApi.requests.kieSandboxWorkspacesGit_fetch(args)
@@ -261,6 +271,7 @@ export function WorkspacesContextProvider(props: Props) {
         password: string;
       };
       insecurelyDisableTlsCertificateValidation?: boolean;
+      disableEncoding?: boolean;
     }) =>
       workspacesSharedWorker.withBus((workspacesWorkerBus) =>
         workspacesWorkerBus.clientApi.requests.kieSandboxWorkspacesGit_getGitServerRefs(args)
@@ -304,7 +315,7 @@ export function WorkspacesContextProvider(props: Props) {
 
   const createWorkspaceFromGitRepository = useCallback(
     async (args: {
-      origin: GistOrigin | GitHubOrigin | BitbucketOrigin | SnippetOrigin;
+      origin: GistOrigin | GitHubOrigin | BitbucketOrigin | BitbucketSnippetOrigin | GitlabOrigin | GitlabSnippetOrigin;
       gitConfig?: { email: string; name: string };
       gitAuthSessionId: string | undefined;
       authInfo?: {
@@ -312,6 +323,7 @@ export function WorkspacesContextProvider(props: Props) {
         password: string;
       };
       insecurelyDisableTlsCertificateValidation?: boolean;
+      disableEncoding?: boolean;
     }) => {
       const workspaceClone = await workspacesSharedWorker.withBus((workspacesWorkerBus) =>
         workspacesWorkerBus.clientApi.requests.kieSandboxWorkspacesGit_clone(args)
@@ -519,6 +531,7 @@ export function WorkspacesContextProvider(props: Props) {
       remoteUrl: URL;
       branch?: string;
       insecurelyDisableTlsCertificateValidation?: boolean;
+      disableEncoding?: boolean;
     }) =>
       workspacesSharedWorker.withBus((workspacesWorkerBus) =>
         workspacesWorkerBus.clientApi.requests.kieSandboxWorkspacesGit_initGitOnExistingWorkspace({
@@ -526,6 +539,7 @@ export function WorkspacesContextProvider(props: Props) {
           remoteUrl: args.remoteUrl.toString(),
           branch: args.branch,
           insecurelyDisableTlsCertificateValidation: args.insecurelyDisableTlsCertificateValidation,
+          disableEncoding: args.disableEncoding,
         })
       ),
     [workspacesSharedWorker]
@@ -537,6 +551,7 @@ export function WorkspacesContextProvider(props: Props) {
       remoteUrl: URL;
       branch: string;
       insecurelyDisableTlsCertificateValidation?: boolean;
+      disableEncoding?: boolean;
     }) =>
       workspacesSharedWorker.withBus((workspacesWorkerBus) =>
         workspacesWorkerBus.clientApi.requests.kieSandboxWorkspacesGit_initGistOnExistingWorkspace({
@@ -544,6 +559,7 @@ export function WorkspacesContextProvider(props: Props) {
           remoteUrl: args.remoteUrl.toString(),
           branch: args.branch,
           insecurelyDisableTlsCertificateValidation: args.insecurelyDisableTlsCertificateValidation,
+          disableEncoding: args.disableEncoding,
         })
       ),
     [workspacesSharedWorker]
@@ -555,6 +571,7 @@ export function WorkspacesContextProvider(props: Props) {
       remoteUrl: URL;
       branch: string;
       insecurelyDisableTlsCertificateValidation?: boolean;
+      disableEncoding?: boolean;
     }) =>
       workspacesSharedWorker.withBus((workspacesWorkerBus) =>
         workspacesWorkerBus.clientApi.requests.kieSandboxWorkspacesGit_initSnippetOnExistingWorkspace({
@@ -562,6 +579,27 @@ export function WorkspacesContextProvider(props: Props) {
           remoteUrl: args.remoteUrl.toString(),
           branch: args.branch,
           insecurelyDisableTlsCertificateValidation: args.insecurelyDisableTlsCertificateValidation,
+          disableEncoding: args.disableEncoding,
+        })
+      ),
+    [workspacesSharedWorker]
+  );
+
+  const initGilabSnippetOnWorkspace = useCallback(
+    async (args: {
+      workspaceId: string;
+      remoteUrl: URL;
+      branch: string;
+      insecurelyDisableTlsCertificateValidation?: boolean;
+      disableEncoding?: boolean;
+    }) =>
+      workspacesSharedWorker.withBus((workspacesWorkerBus) =>
+        workspacesWorkerBus.clientApi.requests.kieSandboxWorkspacesGit_initGitlabSnippetOnExistingWorkspace({
+          workspaceId: args.workspaceId,
+          remoteUrl: args.remoteUrl.toString(),
+          branch: args.branch,
+          insecurelyDisableTlsCertificateValidation: args.insecurelyDisableTlsCertificateValidation,
+          disableEncoding: args.disableEncoding,
         })
       ),
     [workspacesSharedWorker]
@@ -572,12 +610,14 @@ export function WorkspacesContextProvider(props: Props) {
       workspaceId: string;
       gitAuthSessionId: string | undefined;
       insecurelyDisableTlsCertificateValidation?: boolean;
+      disableEncoding?: boolean;
     }) => {
       workspacesSharedWorker.withBus((workspacesWorkerBus) =>
         workspacesWorkerBus.clientApi.requests.kieSandboxWorkspacesGit_changeGitAuthSessionId({
           workspaceId: args.workspaceId,
           gitAuthSessionId: args.gitAuthSessionId,
           insecurelyDisableTlsCertificateValidation: args.insecurelyDisableTlsCertificateValidation,
+          disableEncoding: args.disableEncoding,
         })
       );
     },
@@ -635,6 +675,7 @@ export function WorkspacesContextProvider(props: Props) {
       initGitOnWorkspace,
       initGistOnWorkspace,
       initSnippetOnWorkspace,
+      initGilabSnippetOnWorkspace,
       changeGitAuthSessionId,
       initLocalOnWorkspace,
       isFileModified,
@@ -680,6 +721,7 @@ export function WorkspacesContextProvider(props: Props) {
       initGitOnWorkspace,
       initGistOnWorkspace,
       initSnippetOnWorkspace,
+      initGilabSnippetOnWorkspace,
       changeGitAuthSessionId,
       initLocalOnWorkspace,
       isFileModified,
diff --git a/packages/workspaces-git-fs/src/services/GitService.tsx b/packages/workspaces-git-fs/src/services/GitService.tsx
index 31bdbd5adc7..f23dca523f1 100644
--- a/packages/workspaces-git-fs/src/services/GitService.tsx
+++ b/packages/workspaces-git-fs/src/services/GitService.tsx
@@ -37,6 +37,7 @@ export interface CloneArgs {
     password: string;
   };
   insecurelyDisableTlsCertificateValidation?: boolean;
+  disableEncoding?: boolean;
 }
 
 export interface CommitArgs {
@@ -62,6 +63,7 @@ export interface PushArgs {
     password: string;
   };
   insecurelyDisableTlsCertificateValidation?: boolean;
+  disableEncoding?: boolean;
 }
 
 export interface RemoteRefArgs {
@@ -73,6 +75,7 @@ export interface RemoteRefArgs {
     password: string;
   };
   insecurelyDisableTlsCertificateValidation?: boolean;
+  disableEncoding?: boolean;
 }
 
 export enum FileModificationStatus {
@@ -87,14 +90,22 @@ export type UnstagedModifiedFilesStatusEntryType = {
 export class GitService {
   public constructor(private readonly corsProxy: Promise<string>) {}
 
-  private getRequestHeaders(args: { insecurelyDisableTlsCertificateValidation?: boolean }) {
-    return args.insecurelyDisableTlsCertificateValidation
-      ? {
-          [CorsProxyHeaderKeys.INSECURELY_DISABLE_TLS_CERTIFICATE_VALIDATION]: Boolean(
-            args.insecurelyDisableTlsCertificateValidation
-          ).toString(),
-        }
-      : undefined;
+  private getRequestHeaders(args: { insecurelyDisableTlsCertificateValidation?: boolean; disableEncoding?: boolean }) {
+    if (!args.insecurelyDisableTlsCertificateValidation && !args.disableEncoding) {
+      return undefined;
+    }
+    const headers: Record<string, string> = {
+      ...(args.insecurelyDisableTlsCertificateValidation && {
+        [CorsProxyHeaderKeys.INSECURELY_DISABLE_TLS_CERTIFICATE_VALIDATION]: Boolean(
+          args.insecurelyDisableTlsCertificateValidation
+        ).toString(),
+      }),
+      // If disableEncoding is true, force proxy/server to skip compression
+      ...(args.disableEncoding
+        ? { [CorsProxyHeaderKeys.DISABLE_ENCODING]: Boolean(args.disableEncoding).toString() }
+        : {}),
+    };
+    return headers;
   }
 
   public async listServerRefs(args: {
@@ -104,6 +115,7 @@ export class GitService {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }) {
     return git.listServerRefs({
       http,
@@ -175,6 +187,7 @@ export class GitService {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<FetchResult> {
     return await git.fetch({
       fs: args.fs,
@@ -254,6 +267,7 @@ export class GitService {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }) {
     await git.pull({
       fs: args.fs,
@@ -314,6 +328,7 @@ export class GitService {
       remoteRef: args.remoteRef,
       authInfo: args.authInfo,
       insecurelyDisableTlsCertificateValidation: args.insecurelyDisableTlsCertificateValidation,
+      disableEncoding: args.disableEncoding,
     });
 
     if (serverRemoteRef?.oid && head === serverRemoteRef.oid) return;
diff --git a/packages/workspaces-git-fs/src/services/WorkspaceDescriptorService.tsx b/packages/workspaces-git-fs/src/services/WorkspaceDescriptorService.tsx
index 97a2479734b..c69d0d8fbf2 100644
--- a/packages/workspaces-git-fs/src/services/WorkspaceDescriptorService.tsx
+++ b/packages/workspaces-git-fs/src/services/WorkspaceDescriptorService.tsx
@@ -76,6 +76,7 @@ export class WorkspaceDescriptorService {
     preferredName?: string;
     gitAuthSessionId: string | undefined;
     gitInsecurelyDisableTlsCertificateValidation?: boolean;
+    gitDisableEncoding?: boolean;
   }) {
     const workspace: WorkspaceDescriptor = {
       workspaceId: this.newWorkspaceId(),
@@ -85,6 +86,7 @@ export class WorkspaceDescriptorService {
       lastUpdatedDateISO: new Date().toISOString(),
       gitAuthSessionId: args.gitAuthSessionId,
       gitInsecurelyDisableTlsCertificateValidation: args.gitInsecurelyDisableTlsCertificateValidation,
+      gitDisableEncoding: args.gitDisableEncoding,
     };
     await this.storageService.createOrOverwriteFile(args.fs, this.toStorageFile(workspace));
     return workspace;
@@ -107,7 +109,8 @@ export class WorkspaceDescriptorService {
     workspaceId: string,
     gistUrl: URL,
     branch: string,
-    insecurelyDisableTlsCertificateValidation?: boolean
+    insecurelyDisableTlsCertificateValidation?: boolean,
+    disableEncoding?: boolean
   ) {
     const file = this.toStorageFile({
       ...(await this.get(fs, workspaceId)),
@@ -117,6 +120,7 @@ export class WorkspaceDescriptorService {
         branch,
       },
       gitInsecurelyDisableTlsCertificateValidation: insecurelyDisableTlsCertificateValidation,
+      gitDisableEncoding: disableEncoding,
     });
     await this.storageService.updateFile(fs, file.path, file.getFileContents);
 
@@ -135,7 +139,8 @@ export class WorkspaceDescriptorService {
     workspaceId: string,
     snippetUrl: URL,
     branch: string,
-    insecurelyDisableTlsCertificateValidation?: boolean
+    insecurelyDisableTlsCertificateValidation?: boolean,
+    disableEncoding?: boolean
   ) {
     const file = this.toStorageFile({
       ...(await this.get(fs, workspaceId)),
@@ -145,6 +150,38 @@ export class WorkspaceDescriptorService {
         branch,
       },
       gitInsecurelyDisableTlsCertificateValidation: insecurelyDisableTlsCertificateValidation,
+      gitDisableEncoding: disableEncoding,
+    });
+    await this.storageService.updateFile(fs, file.path, file.getFileContents);
+
+    new Broadcaster().broadcast({
+      channel: workspaceId,
+      message: async () => ({ type: "WS_UPDATE_DESCRIPTOR" }),
+    });
+
+    new Broadcaster().broadcast({
+      channel: WORKSPACES_BROADCAST_CHANNEL,
+      message: async () => ({ type: "WSS_UPDATE", workspaceId }),
+    });
+  }
+
+  public async turnIntoGitlabSnippet(
+    fs: KieSandboxWorkspacesFs,
+    workspaceId: string,
+    snippetUrl: URL,
+    branch: string,
+    insecurelyDisableTlsCertificateValidation?: boolean,
+    disableEncoding?: boolean
+  ) {
+    const file = this.toStorageFile({
+      ...(await this.get(fs, workspaceId)),
+      origin: {
+        kind: WorkspaceKind.GITLAB_SNIPPET,
+        url: snippetUrl.toString(),
+        branch,
+      },
+      gitInsecurelyDisableTlsCertificateValidation: insecurelyDisableTlsCertificateValidation,
+      gitDisableEncoding: disableEncoding,
     });
     await this.storageService.updateFile(fs, file.path, file.getFileContents);
 
@@ -164,7 +201,8 @@ export class WorkspaceDescriptorService {
     workspaceId: string,
     url: URL,
     branch?: string,
-    insecurelyDisableTlsCertificateValidation?: boolean
+    insecurelyDisableTlsCertificateValidation?: boolean,
+    disableEncoding?: boolean
   ) {
     const file = this.toStorageFile({
       ...(await this.get(fs, workspaceId)),
@@ -174,6 +212,7 @@ export class WorkspaceDescriptorService {
         branch: branch ?? GIT_DEFAULT_BRANCH,
       },
       gitInsecurelyDisableTlsCertificateValidation: insecurelyDisableTlsCertificateValidation,
+      gitDisableEncoding: disableEncoding,
     });
     await this.storageService.updateFile(fs, file.path, file.getFileContents);
 
@@ -192,12 +231,14 @@ export class WorkspaceDescriptorService {
     fs: KieSandboxWorkspacesFs,
     workspaceId: string,
     gitAuthSessionId: string | undefined,
-    insecurelyDisableTlsCertificateValidation?: boolean
+    insecurelyDisableTlsCertificateValidation?: boolean,
+    disableEncoding?: boolean
   ) {
     const file = this.toStorageFile({
       ...(await this.get(fs, workspaceId)),
       gitAuthSessionId,
       gitInsecurelyDisableTlsCertificateValidation: insecurelyDisableTlsCertificateValidation,
+      gitDisableEncoding: disableEncoding,
     });
     await this.storageService.updateFile(fs, file.path, file.getFileContents);
 
diff --git a/packages/workspaces-git-fs/src/services/WorkspaceService.tsx b/packages/workspaces-git-fs/src/services/WorkspaceService.tsx
index 796f5e4a78a..41d69fa3196 100644
--- a/packages/workspaces-git-fs/src/services/WorkspaceService.tsx
+++ b/packages/workspaces-git-fs/src/services/WorkspaceService.tsx
@@ -56,6 +56,7 @@ export class WorkspaceService {
     preferredName?: string;
     gitAuthSessionId: string | undefined;
     gitInsecurelyDisableTlsCertificateValidation?: boolean;
+    gitDisableEncoding?: boolean;
   }) {
     const workspace = await this.descriptorsFsService.withReadWriteInMemoryFs(({ fs }) => {
       return this.workspaceDescriptorService.create({
@@ -64,6 +65,7 @@ export class WorkspaceService {
         preferredName: args.preferredName,
         gitAuthSessionId: args.gitAuthSessionId,
         gitInsecurelyDisableTlsCertificateValidation: args.gitInsecurelyDisableTlsCertificateValidation,
+        gitDisableEncoding: args.gitDisableEncoding,
       });
     });
 
diff --git a/packages/workspaces-git-fs/src/worker/WorkspacesWorkerApiImpl.ts b/packages/workspaces-git-fs/src/worker/WorkspacesWorkerApiImpl.ts
index 04d37442a65..9954bf79f3f 100644
--- a/packages/workspaces-git-fs/src/worker/WorkspacesWorkerApiImpl.ts
+++ b/packages/workspaces-git-fs/src/worker/WorkspacesWorkerApiImpl.ts
@@ -36,9 +36,11 @@ import { LocalFile } from "./api/LocalFile";
 import { WorkspaceDescriptor } from "./api/WorkspaceDescriptor";
 import {
   BitbucketOrigin,
+  BitbucketSnippetOrigin,
   GistOrigin,
   GitHubOrigin,
-  SnippetOrigin,
+  GitlabOrigin,
+  GitlabSnippetOrigin,
   WorkspaceKind,
   WorkspaceOrigin,
 } from "./api/WorkspaceOrigin";
@@ -77,13 +79,15 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
     workspaceId: string;
     gitAuthSessionId: string | undefined;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void> {
     return this.args.services.descriptorsFsService.withReadWriteInMemoryFs(({ fs }) => {
       return this.args.services.descriptorService.changeGitAuthSessionId(
         fs,
         args.workspaceId,
         args.gitAuthSessionId,
-        args.insecurelyDisableTlsCertificateValidation
+        args.insecurelyDisableTlsCertificateValidation,
+        args.disableEncoding
       );
     });
   }
@@ -93,6 +97,7 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
     remoteUrl: string;
     branch: string;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void> {
     return this.args.services.descriptorsFsService.withReadWriteInMemoryFs(({ fs }) => {
       return this.args.services.descriptorService.turnIntoGist(
@@ -100,7 +105,8 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
         args.workspaceId,
         new URL(args.remoteUrl),
         args.branch,
-        args.insecurelyDisableTlsCertificateValidation
+        args.insecurelyDisableTlsCertificateValidation,
+        args.disableEncoding
       );
     });
   }
@@ -110,6 +116,7 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
     remoteUrl: string;
     branch: string;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void> {
     return this.args.services.descriptorsFsService.withReadWriteInMemoryFs(({ fs }) => {
       return this.args.services.descriptorService.turnIntoSnippet(
@@ -117,7 +124,27 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
         args.workspaceId,
         new URL(args.remoteUrl),
         args.branch,
-        args.insecurelyDisableTlsCertificateValidation
+        args.insecurelyDisableTlsCertificateValidation,
+        args.disableEncoding
+      );
+    });
+  }
+
+  public async kieSandboxWorkspacesGit_initGitlabSnippetOnExistingWorkspace(args: {
+    workspaceId: string;
+    remoteUrl: string;
+    branch: string;
+    insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
+  }): Promise<void> {
+    return this.args.services.descriptorsFsService.withReadWriteInMemoryFs(({ fs }) => {
+      return this.args.services.descriptorService.turnIntoGitlabSnippet(
+        fs,
+        args.workspaceId,
+        new URL(args.remoteUrl),
+        args.branch,
+        args.insecurelyDisableTlsCertificateValidation,
+        args.disableEncoding
       );
     });
   }
@@ -127,6 +154,7 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
     remoteUrl: string;
     branch?: string;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void> {
     return this.args.services.descriptorsFsService.withReadWriteInMemoryFs(({ fs }) => {
       return this.args.services.descriptorService.turnIntoGit(
@@ -134,7 +162,8 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
         args.workspaceId,
         new URL(args.remoteUrl),
         args.branch,
-        args.insecurelyDisableTlsCertificateValidation
+        args.insecurelyDisableTlsCertificateValidation,
+        args.disableEncoding
       );
     });
   }
@@ -506,16 +535,18 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<GitServerRef[]> {
     return this.args.services.gitService.listServerRefs(args);
   }
 
   public async kieSandboxWorkspacesGit_clone(args: {
-    origin: GistOrigin | GitHubOrigin | BitbucketOrigin | SnippetOrigin;
+    origin: GistOrigin | GitHubOrigin | BitbucketOrigin | BitbucketSnippetOrigin | GitlabOrigin | GitlabSnippetOrigin;
     gitConfig?: { email: string; name: string };
     authInfo?: { username: string; password: string };
     gitAuthSessionId: string | undefined;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<{ workspace: WorkspaceDescriptor; suggestedFirstFile?: WorkspaceWorkerFileDescriptor }> {
     console.log(args);
     return this.createWorkspace({
@@ -523,6 +554,7 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
       origin: args.origin,
       gitAuthSessionId: args.gitAuthSessionId,
       gitInsecurelyDisableTlsCertificateValidation: args.insecurelyDisableTlsCertificateValidation,
+      gitDisableEncoding: args.disableEncoding,
       storeFiles: async (fs, schema, workspace) => {
         await this.args.services.gitService.clone({
           fs,
@@ -532,6 +564,7 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
           authInfo: args.authInfo,
           sourceBranch: args.origin.branch,
           insecurelyDisableTlsCertificateValidation: args.insecurelyDisableTlsCertificateValidation,
+          disableEncoding: args.disableEncoding,
         });
         return this.args.services.workspaceService.getFilteredWorkspaceFileDescriptors(schema, workspace.workspaceId);
       },
@@ -651,6 +684,7 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
     remote: string;
     ref: string;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<FetchResult> {
     return this.args.services.workspaceFsService.withReadWriteInMemoryFs(
       args.workspaceId,
@@ -670,12 +704,14 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
     gitAuthSessionId: string | undefined;
     gitConfig?: { email: string; name: string };
     gitInsecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<{ workspace: WorkspaceDescriptor; suggestedFirstFile?: WorkspaceWorkerFileDescriptor }> {
     return this.createWorkspace({
       preferredName: args.preferredName,
       origin: { kind: WorkspaceKind.LOCAL, branch: GIT_DEFAULT_BRANCH },
       gitAuthSessionId: args.gitAuthSessionId,
       gitInsecurelyDisableTlsCertificateValidation: args.gitInsecurelyDisableTlsCertificateValidation,
+      gitDisableEncoding: args.disableEncoding,
       storeFiles: async (fs, schema, workspace) => {
         const files = args.localFiles
           .filter((file) => !file.path.startsWith(".git/"))
@@ -752,6 +788,7 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
     gitConfig?: { email: string; name: string };
     authInfo?: { username: string; password: string };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void> {
     const workspace = await this.args.services.descriptorsFsService.withReadWriteInMemoryFs(({ fs }) => {
       return this.args.services.descriptorService.get(fs, args.workspaceId);
@@ -770,6 +807,7 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
           },
           authInfo: args.authInfo,
           insecurelyDisableTlsCertificateValidation: args.insecurelyDisableTlsCertificateValidation,
+          disableEncoding: args.disableEncoding,
         });
 
         broadcaster.broadcast({
@@ -794,6 +832,7 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void> {
     return this.args.services.workspaceFsService.withReadWriteInMemoryFs(
       args.workspaceId,
@@ -864,6 +903,7 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
     preferredName?: string;
     gitAuthSessionId: string | undefined;
     gitInsecurelyDisableTlsCertificateValidation?: boolean;
+    gitDisableEncoding?: boolean;
   }) {
     const { workspace, files } = await this.args.services.workspaceService.create({
       storeFiles: args.storeFiles,
@@ -871,6 +911,7 @@ export class WorkspacesWorkerApiImpl implements WorkspacesWorkerApi {
       preferredName: args.preferredName,
       gitAuthSessionId: args.gitAuthSessionId,
       gitInsecurelyDisableTlsCertificateValidation: args.gitInsecurelyDisableTlsCertificateValidation,
+      gitDisableEncoding: args.gitDisableEncoding,
     });
 
     if (files.length <= 0) {
diff --git a/packages/workspaces-git-fs/src/worker/api/WorkspaceDescriptor.tsx b/packages/workspaces-git-fs/src/worker/api/WorkspaceDescriptor.tsx
index d729fc5aa5c..51c72b7f7cf 100644
--- a/packages/workspaces-git-fs/src/worker/api/WorkspaceDescriptor.tsx
+++ b/packages/workspaces-git-fs/src/worker/api/WorkspaceDescriptor.tsx
@@ -29,4 +29,5 @@ export interface WorkspaceDescriptor {
   lastUpdatedDateISO: string;
   gitAuthSessionId: string | undefined;
   gitInsecurelyDisableTlsCertificateValidation?: boolean;
+  gitDisableEncoding?: boolean;
 }
diff --git a/packages/workspaces-git-fs/src/worker/api/WorkspaceOrigin.tsx b/packages/workspaces-git-fs/src/worker/api/WorkspaceOrigin.tsx
index 5e5d3e7286a..4a9dc1f80c2 100644
--- a/packages/workspaces-git-fs/src/worker/api/WorkspaceOrigin.tsx
+++ b/packages/workspaces-git-fs/src/worker/api/WorkspaceOrigin.tsx
@@ -24,9 +24,15 @@ export enum WorkspaceKind {
   GIT = "GIT",
   LOCAL = "LOCAL",
   BITBUCKET_SNIPPET = "BITBUCKET_SNIPPET",
+  GITLAB_SNIPPET = "GITLAB_SNIPPET",
 }
 
-const gitBasedTypeKeys = [WorkspaceKind.GIT, WorkspaceKind.BITBUCKET_SNIPPET, WorkspaceKind.GITHUB_GIST] as const;
+const gitBasedTypeKeys = [
+  WorkspaceKind.GIT,
+  WorkspaceKind.BITBUCKET_SNIPPET,
+  WorkspaceKind.GITHUB_GIST,
+  WorkspaceKind.GITLAB_SNIPPET,
+] as const;
 export type WorkspaceKindGitBased = (typeof gitBasedTypeKeys)[number];
 
 export const isGitBasedWorkspaceKind = (
@@ -35,7 +41,11 @@ export const isGitBasedWorkspaceKind = (
   return gitBasedTypeKeys.some((k) => k === maybeGitBasedType);
 };
 
-const gistLikeTypeKeys = [WorkspaceKind.GITHUB_GIST, WorkspaceKind.BITBUCKET_SNIPPET] as const;
+const gistLikeTypeKeys = [
+  WorkspaceKind.GITHUB_GIST,
+  WorkspaceKind.BITBUCKET_SNIPPET,
+  WorkspaceKind.GITLAB_SNIPPET,
+] as const;
 export type WorkspaceKindGistLike = (typeof gistLikeTypeKeys)[number];
 
 export const isGistLikeWorkspaceKind = (
@@ -44,7 +54,14 @@ export const isGistLikeWorkspaceKind = (
   return gistLikeTypeKeys.some((k) => k === maybeGistLikeType);
 };
 
-export type WorkspaceOrigin = LocalOrigin | GistOrigin | GitHubOrigin | BitbucketOrigin | SnippetOrigin;
+export type WorkspaceOrigin =
+  | LocalOrigin
+  | GistOrigin
+  | GitHubOrigin
+  | BitbucketOrigin
+  | BitbucketSnippetOrigin
+  | GitlabOrigin
+  | GitlabSnippetOrigin;
 
 export interface LocalOrigin {
   kind: WorkspaceKind.LOCAL;
@@ -70,8 +87,20 @@ export interface GistOrigin {
   branch: string;
 }
 
-export interface SnippetOrigin {
+export interface BitbucketSnippetOrigin {
   kind: WorkspaceKind.BITBUCKET_SNIPPET;
   url: string;
   branch: string;
 }
+
+export interface GitlabOrigin {
+  kind: WorkspaceKind.GIT;
+  url: string;
+  branch: string;
+}
+
+export interface GitlabSnippetOrigin {
+  kind: WorkspaceKind.GITLAB_SNIPPET;
+  url: string;
+  branch: string;
+}
diff --git a/packages/workspaces-git-fs/src/worker/api/WorkspacesWorkerGitApi.ts b/packages/workspaces-git-fs/src/worker/api/WorkspacesWorkerGitApi.ts
index c240208ef1c..31b5ed4450c 100644
--- a/packages/workspaces-git-fs/src/worker/api/WorkspacesWorkerGitApi.ts
+++ b/packages/workspaces-git-fs/src/worker/api/WorkspacesWorkerGitApi.ts
@@ -18,7 +18,14 @@
  */
 
 import { WorkspaceDescriptor } from "./WorkspaceDescriptor";
-import { BitbucketOrigin, GistOrigin, GitHubOrigin, SnippetOrigin } from "./WorkspaceOrigin";
+import {
+  BitbucketOrigin,
+  BitbucketSnippetOrigin,
+  GistOrigin,
+  GitHubOrigin,
+  GitlabOrigin,
+  GitlabSnippetOrigin,
+} from "./WorkspaceOrigin";
 import { LocalFile } from "./LocalFile";
 import { WorkspaceWorkerFileDescriptor } from "./WorkspaceWorkerFileDescriptor";
 import { GitServerRef } from "./GitServerRef";
@@ -33,6 +40,7 @@ export interface WorkspacesWorkerGitApi {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<GitServerRef[]>;
 
   kieSandboxWorkspacesGit_hasLocalChanges(args: { workspaceId: string }): Promise<boolean>;
@@ -56,7 +64,7 @@ export interface WorkspacesWorkerGitApi {
   }>;
 
   kieSandboxWorkspacesGit_clone(args: {
-    origin: GistOrigin | GitHubOrigin | BitbucketOrigin | SnippetOrigin;
+    origin: GistOrigin | GitHubOrigin | BitbucketOrigin | BitbucketSnippetOrigin | GitlabOrigin | GitlabSnippetOrigin;
     gitAuthSessionId: string | undefined;
     gitConfig?: {
       email: string;
@@ -67,6 +75,7 @@ export interface WorkspacesWorkerGitApi {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<{
     workspace: WorkspaceDescriptor;
     suggestedFirstFile?: WorkspaceWorkerFileDescriptor;
@@ -83,6 +92,7 @@ export interface WorkspacesWorkerGitApi {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void>;
 
   kieSandboxWorkspacesGit_push(args: {
@@ -96,6 +106,7 @@ export interface WorkspacesWorkerGitApi {
       password: string;
     };
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void>;
 
   kieSandboxWorkspacesGit_deleteBranch(args: { workspaceId: string; ref: string }): Promise<void>;
@@ -150,6 +161,7 @@ export interface WorkspacesWorkerGitApi {
     };
     ref: string;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<FetchResult>;
 
   kieSandboxWorkspacesGit_initGitOnExistingWorkspace(args: {
@@ -157,6 +169,7 @@ export interface WorkspacesWorkerGitApi {
     remoteUrl: string;
     branch?: string;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void>;
 
   kieSandboxWorkspacesGit_initGistOnExistingWorkspace(args: {
@@ -164,6 +177,7 @@ export interface WorkspacesWorkerGitApi {
     remoteUrl: string;
     branch: string;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void>;
 
   kieSandboxWorkspacesGit_initSnippetOnExistingWorkspace(args: {
@@ -171,12 +185,22 @@ export interface WorkspacesWorkerGitApi {
     remoteUrl: string;
     branch: string;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
+  }): Promise<void>;
+
+  kieSandboxWorkspacesGit_initGitlabSnippetOnExistingWorkspace(args: {
+    workspaceId: string;
+    remoteUrl: string;
+    branch: string;
+    insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void>;
 
   kieSandboxWorkspacesGit_changeGitAuthSessionId(args: {
     workspaceId: string;
     gitAuthSessionId: string | undefined;
     insecurelyDisableTlsCertificateValidation?: boolean;
+    disableEncoding?: boolean;
   }): Promise<void>;
 
   kieSandboxWorkspacesGit_initLocalOnExistingWorkspace(args: { workspaceId: string }): Promise<void>;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org