Przeglądaj źródła

Merge remote-tracking branch 'origin/master' into dev

Roman Zabaluev 2 lat temu
rodzic
commit
0a07bb4db5

+ 28 - 0
.github/workflows/create-branch-for-helm.yaml

@@ -0,0 +1,28 @@
+name: prepare-helm-release
+on:
+  repository_dispatch:
+    types: [prepare-helm-release]
+jobs:
+  change-app-version:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - run: |
+          git config user.name github-actions
+          git config user.email github-actions@github.com
+      - name: Change versions
+        run: |
+          git checkout -b release-${{ github.event.client_payload.appversion}}
+          version=$(cat charts/kafka-ui/Chart.yaml  | grep version | awk '{print $2}')
+          version=${version%.*}.$((${version##*.}+1))
+          sed -i "s/version:.*/version: ${version}/" charts/kafka-ui/Chart.yaml
+          sed -i "s/appVersion:.*/appVersion: ${{ github.event.client_payload.appversion}}/" charts/kafka-ui/Chart.yaml
+          git add  charts/kafka-ui/Chart.yaml
+          git commit -m "release ${version}"
+          git push --set-upstream origin release-${{ github.event.client_payload.appversion}}
+      - name: Slack Notification
+        uses: rtCamp/action-slack-notify@v2
+        env:
+          SLACK_TITLE: "release-${{ github.event.client_payload.appversion}}"
+          SLACK_MESSAGE: "A new release of the helm chart has been prepared. Branch name: release-${{ github.event.client_payload.appversion}}"
+          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

+ 33 - 0
.github/workflows/release-serde-api.yaml

@@ -0,0 +1,33 @@
+name: Release-serde-api
+on: workflow_dispatch
+
+jobs:
+  release-serde-api:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - run: |
+          git config user.name github-actions
+          git config user.email github-actions@github.com
+
+      - name: Set up JDK
+        uses: actions/setup-java@v3
+        with:
+          java-version: "17"
+          distribution: "zulu"
+          cache: "maven"
+
+      - id: install-secret-key
+        name: Install GPG secret key
+        run: |
+          cat <(echo -e "${{ secrets.GPG_PRIVATE_KEY }}") | gpg --batch --import
+
+      - name: Publish to Maven Central
+        run: |
+          MVN_VERSION=$(curl -s https://search.maven.org/solrsearch/select?q=g:"com.provectus"+AND+a:"kafka-ui-serde-api" | grep -o '"latestVersion": *"[^"]*"' | grep -o '"[^"]*"$' | sed 's/"//g')
+          MVN_VERSION=$(echo "$MVN_VERSION" | awk 'BEGIN{FS=OFS="."} {$2+=1} 1')
+          mvn -B -ntp versions:set -DnewVersion=$MVN_VERSION -pl kafka-ui-serde-api
+          mvn source:jar  javadoc:jar  package  gpg:sign -Dgpg.passphrase=${{ secrets.GPG_PASSPHRASE }} -Dserver.username=${{ secrets.NEXUS_USERNAME }} -Dserver.password=${{ secrets.NEXUS_PASSWORD }} nexus-staging:deploy   -pl kafka-ui-serde-api  -s settings.xml

+ 8 - 26
.github/workflows/release.yaml

@@ -87,32 +87,14 @@ jobs:
 
   charts:
     runs-on: ubuntu-latest
+    permissions:
+      actions: write
     needs: release
     steps:
-      - uses: actions/checkout@v3
+      - name: Repository Dispatch
+        uses: peter-evans/repository-dispatch@v2
         with:
-          fetch-depth: 1
-
-      - run: |
-          git config user.name github-actions
-          git config user.email github-actions@github.com
-
-      - uses: azure/setup-helm@v1
-
-      - name: update chart version
-        run: |
-          export version=${{needs.release.outputs.version}}
-          sed -i "s/version:.*/version: ${version}/" charts/kafka-ui/Chart.yaml
-          sed -i "s/appVersion:.*/appVersion: ${version}/" charts/kafka-ui/Chart.yaml
-
-      - name: add chart
-        run: |
-          export VERSION=${{needs.release.outputs.version}}
-          MSG=$(helm package --app-version ${VERSION} charts/kafka-ui)
-          git fetch origin
-          git stash
-          git checkout -b gh-pages origin/gh-pages
-          helm repo index .
-          git add -f ${MSG##*/} index.yaml
-          git commit -m "release ${VERSION}"
-          git push
+          token: ${{ secrets.GITHUB_TOKEN }}
+          repository: provectus/kafka-ui
+          event-type: prepare-helm-release
+          client-payload: '{"appversion": "${{ needs.release.outputs.version }}"}'

+ 1 - 1
kafka-ui-api/pom.xml

@@ -45,7 +45,7 @@
         <dependency>
             <groupId>com.provectus</groupId>
             <artifactId>kafka-ui-serde-api</artifactId>
-            <version>${project.version}</version>
+            <version>${kafka-ui-serde-api.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.kafka</groupId>

+ 17 - 2
kafka-ui-react-app/src/components/App.tsx

@@ -1,6 +1,11 @@
 import React, { Suspense, useCallback } from 'react';
-import { Routes, Route, useLocation } from 'react-router-dom';
-import { clusterPath, getNonExactPath } from 'lib/paths';
+import { Routes, Route, useLocation, Navigate } from 'react-router-dom';
+import {
+  accessErrorPage,
+  clusterPath,
+  errorPage,
+  getNonExactPath,
+} from 'lib/paths';
 import Nav from 'components/Nav/Nav';
 import PageLoader from 'components/common/PageLoader/PageLoader';
 import Dashboard from 'components/Dashboard/Dashboard';
@@ -20,6 +25,7 @@ import DiscordIcon from 'components/common/Icons/DiscordIcon';
 import ConfirmationModal from './common/ConfirmationModal/ConfirmationModal';
 import { ConfirmContextProvider } from './contexts/ConfirmContext';
 import { GlobalSettingsProvider } from './contexts/GlobalSettingsContext';
+import ErrorPage from './ErrorPage/ErrorPage';
 
 const queryClient = new QueryClient({
   defaultOptions: {
@@ -123,6 +129,15 @@ const App: React.FC = () => {
                     path={getNonExactPath(clusterPath())}
                     element={<ClusterPage />}
                   />
+                  <Route
+                    path={accessErrorPage}
+                    element={<ErrorPage status={403} text="Access is Denied" />}
+                  />
+                  <Route path={errorPage} element={<ErrorPage />} />
+                  <Route
+                    path="*"
+                    element={<Navigate to={errorPage} replace />}
+                  />
                 </Routes>
               </S.Container>
               <Toaster position="bottom-right" />

+ 9 - 1
kafka-ui-react-app/src/components/Brokers/Brokers.tsx

@@ -3,11 +3,19 @@ import { Route, Routes } from 'react-router-dom';
 import { getNonExactPath, RouteParams } from 'lib/paths';
 import BrokersList from 'components/Brokers/BrokersList/BrokersList';
 import Broker from 'components/Brokers/Broker/Broker';
+import SuspenseQueryComponent from 'components/common/SuspenseQueryComponent/SuspenseQueryComponent';
 
 const Brokers: React.FC = () => (
   <Routes>
     <Route index element={<BrokersList />} />
-    <Route path={getNonExactPath(RouteParams.brokerId)} element={<Broker />} />
+    <Route
+      path={getNonExactPath(RouteParams.brokerId)}
+      element={
+        <SuspenseQueryComponent>
+          <Broker />
+        </SuspenseQueryComponent>
+      }
+    />
   </Routes>
 );
 

+ 6 - 1
kafka-ui-react-app/src/components/Connect/Connect.tsx

@@ -9,6 +9,7 @@ import {
   clusterConnectorsPath,
 } from 'lib/paths';
 import useAppParams from 'lib/hooks/useAppParams';
+import SuspenseQueryComponent from 'components/common/SuspenseQueryComponent/SuspenseQueryComponent';
 
 import ListPage from './List/ListPage';
 import New from './New/New';
@@ -23,7 +24,11 @@ const Connect: React.FC = () => {
       <Route path={clusterConnectorNewRelativePath} element={<New />} />
       <Route
         path={getNonExactPath(clusterConnectConnectorRelativePath)}
-        element={<DetailsPage />}
+        element={
+          <SuspenseQueryComponent>
+            <DetailsPage />
+          </SuspenseQueryComponent>
+        }
       />
       <Route
         path={clusterConnectConnectorsRelativePath}

+ 20 - 0
kafka-ui-react-app/src/components/ErrorPage/ErrorPage.styled.ts

@@ -0,0 +1,20 @@
+import styled from 'styled-components';
+
+export const Wrapper = styled.div`
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  flex-direction: column;
+  gap: 20px;
+  margin-top: 100px;
+`;
+
+export const Number = styled.div`
+  font-size: 100px;
+  color: ${({ theme }) => theme.errorPage.text};
+  line-height: initial;
+`;
+
+export const Text = styled.div`
+  font-size: 20px;
+`;

+ 28 - 0
kafka-ui-react-app/src/components/ErrorPage/ErrorPage.tsx

@@ -0,0 +1,28 @@
+import React from 'react';
+import { Button } from 'components/common/Button/Button';
+
+import * as S from './ErrorPage.styled';
+
+interface Props {
+  status?: number;
+  text?: string;
+  btnText?: string;
+}
+
+const ErrorPage: React.FC<Props> = ({
+  status = 404,
+  text = 'Page is not found',
+  btnText = 'Go Back to Dashboard',
+}) => {
+  return (
+    <S.Wrapper>
+      <S.Number>{status}</S.Number>
+      <S.Text>{text}</S.Text>
+      <Button buttonType="primary" buttonSize="M" to="/">
+        {btnText}
+      </Button>
+    </S.Wrapper>
+  );
+};
+
+export default ErrorPage;

+ 24 - 0
kafka-ui-react-app/src/components/ErrorPage/__tests__/ErrorPage.spec.tsx

@@ -0,0 +1,24 @@
+import React from 'react';
+import { screen } from '@testing-library/react';
+import { render } from 'lib/testHelpers';
+import ErrorPage from 'components/ErrorPage/ErrorPage';
+
+describe('ErrorPage', () => {
+  it('should check Error Page rendering with default text', () => {
+    render(<ErrorPage />);
+    expect(screen.getByText('404')).toBeInTheDocument();
+    expect(screen.getByText('Page is not found')).toBeInTheDocument();
+    expect(screen.getByText('Go Back to Dashboard')).toBeInTheDocument();
+  });
+  it('should check Error Page rendering with custom text', () => {
+    const props = {
+      status: 403,
+      text: 'access is denied',
+      btnText: 'Go back',
+    };
+    render(<ErrorPage {...props} />);
+    expect(screen.getByText(props.status)).toBeInTheDocument();
+    expect(screen.getByText(props.text)).toBeInTheDocument();
+    expect(screen.getByText(props.btnText)).toBeInTheDocument();
+  });
+});

+ 6 - 0
kafka-ui-react-app/src/components/Schemas/Details/Details.tsx

@@ -20,6 +20,7 @@ import {
   SCHEMA_LATEST_FETCH_ACTION,
   selectAllSchemaVersions,
   getSchemaLatest,
+  getAreSchemaLatestRejected,
 } from 'redux/reducers/schemas/schemasSlice';
 import { showServerError } from 'lib/errorHandling';
 import { resetLoaderById } from 'redux/reducers/loader/loaderSlice';
@@ -55,6 +56,7 @@ const Details: React.FC = () => {
   const versions = useAppSelector((state) => selectAllSchemaVersions(state));
   const schema = useAppSelector(getSchemaLatest);
   const isFetched = useAppSelector(getAreSchemaLatestFulfilled);
+  const isRejected = useAppSelector(getAreSchemaLatestRejected);
   const areVersionsFetched = useAppSelector(getAreSchemaVersionsFulfilled);
 
   const columns = React.useMemo(
@@ -78,6 +80,10 @@ const Details: React.FC = () => {
     }
   };
 
+  if (isRejected) {
+    navigate('/404');
+  }
+
   if (!isFetched || !schema) {
     return <PageLoader />;
   }

+ 6 - 0
kafka-ui-react-app/src/components/Schemas/Edit/Edit.tsx

@@ -25,6 +25,7 @@ import {
   SCHEMA_LATEST_FETCH_ACTION,
   getAreSchemaLatestFulfilled,
   schemaUpdated,
+  getAreSchemaLatestRejected,
 } from 'redux/reducers/schemas/schemasSlice';
 import PageLoader from 'components/common/PageLoader/PageLoader';
 import { resetLoaderById } from 'redux/reducers/loader/loaderSlice';
@@ -54,6 +55,7 @@ const Edit: React.FC = () => {
 
   const schema = useAppSelector((state) => getSchemaLatest(state));
   const isFetched = useAppSelector(getAreSchemaLatestFulfilled);
+  const isRejected = useAppSelector(getAreSchemaLatestRejected);
 
   const formatedSchema = React.useMemo(() => {
     return schema?.schemaType === SchemaType.PROTOBUF
@@ -98,6 +100,10 @@ const Edit: React.FC = () => {
     }
   };
 
+  if (isRejected) {
+    navigate('/404');
+  }
+
   if (!isFetched || !schema) {
     return <PageLoader />;
   }

+ 9 - 1
kafka-ui-react-app/src/components/Topics/Topics.tsx

@@ -6,6 +6,7 @@ import {
   getNonExactPath,
   RouteParams,
 } from 'lib/paths';
+import SuspenseQueryComponent from 'components/common/SuspenseQueryComponent/SuspenseQueryComponent';
 
 import New from './New/New';
 import ListPage from './List/ListPage';
@@ -16,7 +17,14 @@ const Topics: React.FC = () => (
     <Route index element={<ListPage />} />
     <Route path={clusterTopicNewRelativePath} element={<New />} />
     <Route path={clusterTopicCopyRelativePath} element={<New />} />
-    <Route path={getNonExactPath(RouteParams.topicName)} element={<Topic />} />
+    <Route
+      path={getNonExactPath(RouteParams.topicName)}
+      element={
+        <SuspenseQueryComponent>
+          <Topic />
+        </SuspenseQueryComponent>
+      }
+    />
   </Routes>
 );
 

+ 29 - 0
kafka-ui-react-app/src/components/common/SuspenseQueryComponent/SuspenseQueryComponent.tsx

@@ -0,0 +1,29 @@
+import React, { PropsWithChildren } from 'react';
+import { ErrorBoundary } from 'react-error-boundary';
+import { Navigate } from 'react-router-dom';
+
+const ErrorComponent: React.FC<{ error: Error }> = ({ error }) => {
+  const errorStatus = (error as unknown as Response)?.status
+    ? (error as unknown as Response).status
+    : '404';
+
+  return <Navigate to={`/${errorStatus}`} />;
+};
+
+/**
+ * @description
+ * basic idea that you can not choose a wrong url, that is why you are safe, but when
+ * the user tries to manipulate some url to get the the desired result and the BE returns 404
+ * it will be propagated to this component and redirected
+ *
+ * !!NOTE!! But only use this Component for GET query Throw error cause maybe in the future inner functionality may change
+ * */
+const SuspenseQueryComponent: React.FC<PropsWithChildren<unknown>> = ({
+  children,
+}) => {
+  return (
+    <ErrorBoundary FallbackComponent={ErrorComponent}>{children}</ErrorBoundary>
+  );
+};
+
+export default SuspenseQueryComponent;

+ 37 - 0
kafka-ui-react-app/src/components/common/SuspenseQueryComponent/__test__/SuspenseQueryComponent.spec.tsx

@@ -0,0 +1,37 @@
+import React from 'react';
+import { render } from 'lib/testHelpers';
+import { screen } from '@testing-library/react';
+import SuspenseQueryComponent from 'components/common/SuspenseQueryComponent/SuspenseQueryComponent';
+
+const fallback = 'fallback';
+
+jest.mock('react-router-dom', () => ({
+  ...jest.requireActual('react-router-dom'),
+  Navigate: () => <div>{fallback}</div>,
+}));
+
+describe('SuspenseQueryComponent', () => {
+  const text = 'text';
+
+  it('should render the inner component if no error occurs', () => {
+    render(<SuspenseQueryComponent>{text}</SuspenseQueryComponent>);
+    expect(screen.getByText(text)).toBeInTheDocument();
+  });
+
+  it('should not render the inner component and call navigate', () => {
+    // throwing intentional For error boundaries to work
+    jest.spyOn(console, 'error').mockImplementation(() => undefined);
+    const Component = () => {
+      throw new Error('new Error');
+    };
+
+    render(
+      <SuspenseQueryComponent>
+        <Component />
+      </SuspenseQueryComponent>
+    );
+    expect(screen.queryByText(text)).not.toBeInTheDocument();
+    expect(screen.getByText(fallback)).toBeInTheDocument();
+    jest.clearAllMocks();
+  });
+});

+ 3 - 0
kafka-ui-react-app/src/lib/paths.ts

@@ -23,6 +23,9 @@ export enum RouteParams {
 
 export const getNonExactPath = (path: string) => `${path}/*`;
 
+export const errorPage = '/404';
+export const accessErrorPage = '/403';
+
 export const clusterPath = (
   clusterName: ClusterName = RouteParams.clusterName
 ) => `/ui/clusters/${clusterName}`;

+ 5 - 0
kafka-ui-react-app/src/redux/reducers/schemas/schemasSlice.ts

@@ -134,6 +134,11 @@ export const getAreSchemaLatestFulfilled = createSelector(
   createFetchingSelector(SCHEMA_LATEST_FETCH_ACTION),
   (status) => status === AsyncRequestStatus.fulfilled
 );
+export const getAreSchemaLatestRejected = createSelector(
+  createFetchingSelector(SCHEMA_LATEST_FETCH_ACTION),
+  (status) => status === AsyncRequestStatus.rejected
+);
+
 export const getAreSchemaVersionsFulfilled = createSelector(
   createFetchingSelector(SCHEMAS_VERSIONS_FETCH_ACTION),
   (status) => status === AsyncRequestStatus.fulfilled

+ 3 - 0
kafka-ui-react-app/src/theme/theme.ts

@@ -581,6 +581,9 @@ const theme = {
   statictics: {
     createdAtColor: Colors.neutral[50],
   },
+  errorPage: {
+    text: Colors.blue[45],
+  },
 };
 
 export type ThemeType = typeof theme;

+ 120 - 25
kafka-ui-serde-api/pom.xml

@@ -1,28 +1,123 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<project
+	xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>kafka-ui</artifactId>
-        <groupId>com.provectus</groupId>
-        <version>0.0.1-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>kafka-ui-serde-api</artifactId>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-install-plugin</artifactId>
-                <version>2.5.2</version>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <version>3.0.2</version>
-            </plugin>
-        </plugins>
-
-    </build>
+	<modelVersion>4.0.0</modelVersion>
+	<packaging>jar</packaging>
+	<properties>
+		<maven.compiler.source>17</maven.compiler.source>
+		<maven.compiler.target>17</maven.compiler.target>
+	</properties>
+	<distributionManagement>
+		<snapshotRepository>
+			<id>ossrh</id>
+			<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
+		</snapshotRepository>
+		<repository>
+			<id>ossrh</id>
+			<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+		</repository>
+	</distributionManagement>
+	<name>kafka-ui-serde-api</name>
+	<description>kafka-ui-serde-api</description>
+	<url>http://github.com/provectus/kafka-ui</url>
+	<licenses>
+		<license>
+			<name>The Apache License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+		</license>
+	</licenses>
+	<developers>
+		<developer>
+			<name>Provectus</name>
+			<email>maintainers.kafka-ui@provectus.com</email>
+			<organization>Provectus</organization>
+			<organizationUrl>https://provectus.com</organizationUrl>
+		</developer>
+	</developers>
+	<scm>
+		<connection>scm:git:git://github.com/provectus/kafka-ui.git</connection>
+		<developerConnection>scm:git:ssh://github.com:provectus/kafka-ui.git</developerConnection>
+		<url>https://github.com/provectus/kafka-ui</url>
+	</scm>
+	<groupId>com.provectus</groupId>
+	<artifactId>kafka-ui-serde-api</artifactId>
+	<version>1.0.0</version>
+	<build>
+		<pluginManagement>
+			<plugins>
+				<plugin>
+					<groupId>org.apache.maven.plugins</groupId>
+					<artifactId>maven-install-plugin</artifactId>
+					<version>2.5.2</version>
+				</plugin>
+				<plugin>
+					<groupId>org.apache.maven.plugins</groupId>
+					<artifactId>maven-jar-plugin</artifactId>
+					<version>3.0.2</version>
+				</plugin>
+				<plugin>
+					<groupId>org.sonatype.plugins</groupId>
+					<artifactId>nexus-staging-maven-plugin</artifactId>
+					<version>1.6.13</version>
+					<extensions>true</extensions>
+					<configuration>
+						<serverId>ossrh</serverId>
+						<nexusUrl>https://s01.oss.sonatype.org/</nexusUrl>
+						<autoReleaseAfterClose>true</autoReleaseAfterClose>
+					</configuration>
+				</plugin>
+				<plugin>
+					<groupId>org.apache.maven.plugins</groupId>
+					<artifactId>maven-source-plugin</artifactId>
+					<version>2.2.1</version>
+					<executions>
+						<execution>
+							<id>attach-sources</id>
+							<goals>
+								<goal>jar-no-fork</goal>
+							</goals>
+						</execution>
+					</executions>
+				</plugin>
+				<plugin>
+					<groupId>org.apache.maven.plugins</groupId>
+					<artifactId>maven-javadoc-plugin</artifactId>
+					<configuration>
+						<source>8</source>
+					</configuration>
+					<version>3.4.1</version>
+					<executions>
+						<execution>
+							<id>attach-javadocs</id>
+							<goals>
+								<goal>jar</goal>
+							</goals>
+						</execution>
+					</executions>
+				</plugin>
+				<plugin>
+					<groupId>org.apache.maven.plugins</groupId>
+					<artifactId>maven-gpg-plugin</artifactId>
+					<executions>
+						<execution>
+							<id>sign-artifacts</id>
+							<phase>verify</phase>
+							<goals>
+								<goal>sign</goal>
+							</goals>
+						</execution>
+					</executions>
+					<configuration>
+						<!-- Prevent gpg from using pinentry programs -->
+						<gpgArguments>
+							<arg>--pinentry-mode</arg>
+							<arg>loopback</arg>
+						</gpgArguments>
+					</configuration>
+				</plugin>
+			</plugins>
+		</pluginManagement>
+	</build>
 </project>

+ 1 - 0
pom.xml

@@ -41,6 +41,7 @@
         <snakeyaml.version>1.33</snakeyaml.version>
         <spring-boot.version>2.7.5</spring-boot.version>
         <spring-security.version>5.7.5</spring-security.version>
+        <kafka-ui-serde-api.version>1.0.0</kafka-ui-serde-api.version>
 
         <!-- Test dependency versions -->
         <junit.version>5.9.1</junit.version>

+ 17 - 0
settings.xml

@@ -0,0 +1,17 @@
+<settings>
+  <servers>
+    <server>
+     <id>ossrh</id>
+     <username>${server.username}</username>
+     <password>${server.password}</password>
+    </server>
+  </servers>
+  <profiles>
+    <profile>
+      <id>ossrh</id>
+      <activation>
+        <activeByDefault>true</activeByDefault>
+      </activation>
+    </profile>
+  </profiles>
+</settings>