Skip to content

Commit

Permalink
Merge pull request #193 from atlassian/ARC-2494-redirect-from-get-sta…
Browse files Browse the repository at this point in the history
…rted

Arc-2494 redirect from get started
  • Loading branch information
rachellerathbone authored Nov 6, 2023
2 parents dec8026 + db0cef1 commit d7457d2
Show file tree
Hide file tree
Showing 10 changed files with 201 additions and 25 deletions.
3 changes: 3 additions & 0 deletions app/jenkins-for-jira-ui/src/__mocks__/@forge/bridge/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export const invoke = jest.fn();
export const router = {
navigate: jest.fn()
};
46 changes: 46 additions & 0 deletions app/jenkins-for-jira-ui/src/api/redirectFromGetStarted.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { invoke, router } from '@forge/bridge';
import { redirectFromGetStarted } from './redirectFromGetStarted';

beforeEach(() => {
jest.clearAllMocks();
});

describe('redirectFromGetStarted', () => {
it('should call invoke and router.navigate with the correct parameters from get started page', async () => {
const contextData = {
siteUrl: 'https://testjirasite.com',
appId: '1234-567-890',
environmentId: '93-2348248121-3428-345734593',
moduleKey: 'get-started-page'
};

(invoke as jest.Mock).mockResolvedValue(contextData);
await redirectFromGetStarted();
expect(invoke).toHaveBeenCalledWith('redirectFromGetStarted');
expect(router.navigate).toHaveBeenCalledWith(
`${contextData.siteUrl}/jira/settings/apps/${contextData.appId}/${contextData.environmentId}/`
);
});

it('should call invoke but should not call router.navigate with the correct parameters from admin page',
async () => {
const contextData = {
siteUrl: 'https://testjirasite.com',
appId: '1234-567-890',
environmentId: '93-2348248121-3428-345734593',
moduleKey: 'not-get-started-page'
};

(invoke as jest.Mock).mockResolvedValue(contextData);
await redirectFromGetStarted();
expect(invoke).toHaveBeenCalledWith('redirectFromGetStarted');
expect(router.navigate).not.toHaveBeenCalledWith(
`${contextData.siteUrl}/jira/settings/apps/${contextData.appId}/${contextData.environmentId}/`
);
});

it('should handle errors gracefully', async () => {
(invoke as jest.Mock).mockRejectedValue(new Error('Test error'));
await expect(redirectFromGetStarted()).rejects.toThrow('Test error');
});
});
28 changes: 28 additions & 0 deletions app/jenkins-for-jira-ui/src/api/redirectFromGetStarted.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { invoke, router } from '@forge/bridge';

interface Context {
siteUrl: string;
appId: string;
environmentId: string;
moduleKey: string;
}

const redirectFromGetStarted = async (): Promise<string> => {
const context: Context = await invoke('redirectFromGetStarted');
const {
siteUrl,
appId,
environmentId,
moduleKey
} = context;

if (moduleKey === 'get-started-page') {
router.navigate(`${siteUrl}/jira/settings/apps/${appId}/${environmentId}/`);
}

return moduleKey;
};

export {
redirectFromGetStarted
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { useHistory } from 'react-router';
import { ButtonGroup } from '@atlaskit/button';
import Spinner from '@atlaskit/spinner';
import Button from '@atlaskit/button/standard-button';
import PageHeader from '@atlaskit/page-header';
import { EmptyState } from '../EmptyState/EmptyState';
Expand All @@ -16,19 +17,27 @@ import {
AnalyticsScreenEventsEnum,
AnalyticsUiEventsEnum
} from '../../common/analytics/analytics-events';
import { redirectFromGetStarted } from '../../api/redirectFromGetStarted';

const JenkinsServerList = (): JSX.Element => {
const history = useHistory();
const analyticsClient = new AnalyticsClient();
const [jenkinsServers, setJenkinsServers] = useState<JenkinsServer[]>();
const [moduleKey, setModuleKey] = useState<string>();
const fetchAllJenkinsServers = async () => {
const servers = await getAllJenkinsServers() || [];
setJenkinsServers(servers);
};

const redirectToAdminPage = useCallback(async () => {
const currentModuleKey = await redirectFromGetStarted();
setModuleKey(currentModuleKey);
}, []);

useEffect(() => {
fetchAllJenkinsServers();
}, []);
redirectToAdminPage();
}, [redirectToAdminPage]);

if (!jenkinsServers) {
return <JenkinsSpinner secondaryClassName={spinnerHeight} />;
Expand Down Expand Up @@ -56,29 +65,44 @@ const JenkinsServerList = (): JSX.Element => {
</ButtonGroup>
);

return jenkinsServers?.length ? (
<>
<div className={headerContainer}>
<PageHeader actions={pageHeaderActions}>Jenkins configuration</PageHeader>
</div>
let contentToRender;

<StyledDescription>
After you connect your Jenkins server to Jira and send a deployment
event from your CI/CD tool, you will be able to view development
information within your linked Jira issue and view deployment pipelines
over a timeline with insights.
</StyledDescription>
if (jenkinsServers?.length && moduleKey === 'jenkins-for-jira-ui-admin-page') {
contentToRender = (
<>
<div className={headerContainer}>
<PageHeader actions={pageHeaderActions}>Jenkins configuration</PageHeader>
</div>
<StyledDescription>
After you connect your Jenkins server to Jira and send a deployment
event from your CI/CD tool, you will be able to view development
information within your linked Jira issue and view deployment pipelines
over a timeline with insights.
</StyledDescription>
<ConnectedServers jenkinsServerList={jenkinsServers} refreshServers={fetchAllJenkinsServers} />
</>
);
} else if (moduleKey === 'get-started-page') {
contentToRender = (
<>
<div className={headerContainer}>
<PageHeader>Jenkins configuration</PageHeader>
</div>
<Spinner size='large' />
</>
);
} else {
contentToRender = (
<>
<div className={headerContainer}>
<PageHeader>Jenkins configuration</PageHeader>
</div>
<EmptyState />
</>
);
}

<ConnectedServers jenkinsServerList={jenkinsServers} refreshServers={fetchAllJenkinsServers} />
</>
) : (
<>
<div className={headerContainer}>
<PageHeader>Jenkins configuration</PageHeader>
</div>
<EmptyState />
</>
);
return contentToRender;
};

export {
Expand Down
17 changes: 17 additions & 0 deletions app/manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,52 @@ modules:
title: Jenkins for Jira
layout: basic
icon: https://marketplace-cdn.atlassian.com/files/0c45cd96-ccf1-4490-9df4-307dded2f6e0?fileType=image&mode=full-fit

- key: get-started-page
resource: main
resolver:
function: redirectFromGetStarted
title: Jenkins for Jira
layout: basic
icon: https://marketplace-cdn.atlassian.com/files/0c45cd96-ccf1-4490-9df4-307dded2f6e0?fileType=image&mode=full-fit
useAsGetStarted: true

webtrigger:
- key: jenkins-webtrigger
function: handle-jenkins-request
- key: reset-jenkins-webtrigger
function: reset-jenkins-request

devops:deploymentInfoProvider:
- key: deployment-info-provider
homeUrl: https://github.com/jenkinsci/atlassian-jira-software-cloud-plugin
logoUrl: https://marketplace-cdn.atlassian.com/files/0c45cd96-ccf1-4490-9df4-307dded2f6e0?fileType=image&mode=full-fit
name:
value: Jenkins for Jira

devops:buildInfoProvider:
- key: build-info-provider
homeUrl: https://github.com/jenkinsci/atlassian-jira-software-cloud-plugin
logoUrl: https://marketplace-cdn.atlassian.com/files/0c45cd96-ccf1-4490-9df4-307dded2f6e0?fileType=image&mode=full-fit
name:
value: Jenkins for Jira

function:
- key: resolver
handler: index.resolver
- key: redirectFromGetStarted
handler: index.redirectFromGetStarted
- key: handle-jenkins-request
handler: index.handleJenkinsRequest
- key: reset-jenkins-request
handler: index.handleResetJenkinsRequest

resources:
- key: main
path: jenkins-for-jira-ui/build
tunnel:
port: 3000

app:
id: ari:cloud:ecosystem::app/df76f661-4cbe-4768-a119-13992dc4ce2d
# This is caused by a forge bug related to deserialising externally allocated memory. TODO: Remove when fix comes out
Expand Down
3 changes: 2 additions & 1 deletion app/src/common/metric-names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export const metricResolverEmitter = {
getAllJenkinsServers: `${server}.getAllServers.emitted`,
getJenkinsServerWithSecret: `${server}.getWithSecretServer.emitted`,
disconnectJenkinsServer: `${server}.disconnectServer.emitted`,
generateNewSecretForServer: `${server}.generateNewSecret.emitted`
generateNewSecretForServer: `${server}.generateNewSecret.emitted`,
redirectFromGetStartedPage: `${server}.getStartedRedirect.emitted`
};
3 changes: 2 additions & 1 deletion app/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import resolver from './resolvers';
import { redirectFromGetStarted } from './utils/redirect-from-get-started';
import handleJenkinsRequest from './webtrigger/handle-jenkins-request';
import { handleResetJenkinsRequest } from './webtrigger/handle-reset-jenkins-request';

// webtriggers
export { handleJenkinsRequest, handleResetJenkinsRequest };

// resolvers
export { resolver };
export { resolver, redirectFromGetStarted };
7 changes: 7 additions & 0 deletions app/src/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { deleteDeployments } from './jira-client/delete-deployments';
import { adminPermissionCheck } from './check-permissions';
import { metricResolverEmitter } from './common/metric-names';
import { generateNewSecret } from './storage/generate-new-secret';
import { RedirectFromGetStarted, redirectFromGetStarted } from './utils/redirect-from-get-started';

const resolver = new Resolver();

Expand Down Expand Up @@ -73,4 +74,10 @@ resolver.define('fetchCloudId', async (req): Promise<string> => {
return req.context.cloudId;
});

resolver.define('redirectFromGetStarted', async (req): Promise<RedirectFromGetStarted> => {
await adminPermissionCheck(req);
internalMetrics.counter(metricResolverEmitter.generateNewSecretForServer).incr();
return redirectFromGetStarted(req);
});

export default resolver.getDefinitions();
30 changes: 30 additions & 0 deletions app/src/utils/redirect-from-get-started.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { redirectFromGetStarted, RedirectFromGetStarted } from './redirect-from-get-started';

describe('redirectFromGetStarted', () => {
it('should return the expected RedirectFromGetStarted object', () => {
const mockRequest = {
context: {
siteUrl: 'https://testjira.com',
appId: 'df76f661-4cbe-4768-a119-13992dc4ce2d',
environmentId: '1831-1281423-12389342983',
moduleKey: 'some-page'
},
};

const result: RedirectFromGetStarted = redirectFromGetStarted(mockRequest);
const {
siteUrl,
appId,
environmentId,
moduleKey
} = mockRequest.context;
const expected: RedirectFromGetStarted = {
siteUrl,
appId,
environmentId,
moduleKey
};

expect(result).toEqual(expected);
});
});
19 changes: 19 additions & 0 deletions app/src/utils/redirect-from-get-started.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export type RedirectFromGetStarted = {
siteUrl: string,
appId: string,
environmentId: string,
moduleKey: string
};

const redirectFromGetStarted = (request: any): RedirectFromGetStarted => {
const { siteUrl, environmentId, moduleKey } = request.context;
const appId = 'df76f661-4cbe-4768-a119-13992dc4ce2d';
return {
siteUrl,
appId,
environmentId,
moduleKey
};
};

export { redirectFromGetStarted };

0 comments on commit d7457d2

Please sign in to comment.