Skip to content

Commit 00f2b2c

Browse files
committed
take out hardcoded URL, fix tests and README
1 parent ee8cfc7 commit 00f2b2c

File tree

5 files changed

+229
-125
lines changed

5 files changed

+229
-125
lines changed

plugins/sonarqube-issues/README.md

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ This plugin requires a proxy to SonarQube. To set up:
3131
- Create a proxy:
3232

3333
- Navigate to Plugins, then click on the Proxies tab, then click on Create Proxy
34-
- Give the proxy a name, then click on Add URL
35-
- For the URL Prefix, type in the base URL of your SonarQube instance. Default for cloud is `https://sonarcloud.io`. **This URL prefix should be exactly the same as the value of the baseURL variable in [SonarqubeIssues.tsx](src/components/SonarqubeIssues.tsx) - If you are self-hosting SonarQube, you will have to put your own base URL in both places!**
36-
- Click on Add Header and add a header whose name is `Authorization` and whose value is `Bearer {{secrets.sonarqube_plugin}}` (include the curly braces!)
34+
- Give the proxy a name, like SonarQube Proxy, then click on Add URL.
35+
- For the URL Prefix, type in the API base URL of your SonarQube instance. The default for cloud is `https://sonarcloud.io`. **If you are self-hosting SonarQube, you will have to put in your own base URL instead.**
36+
- Click on Add Header and add a header whose name is `Authorization` and whose value is `Bearer {{{secrets.sonarqube_plugin}}}` (include the curly braces!)
3737

3838
- Once you are done, the proxy should look like the below:
3939

@@ -53,14 +53,26 @@ Now, you can build and add the plugin.
5353
- In The **Plugin code** section, upload the `dist/ui.html` file you just built.
5454
- Click on **Save plugin**
5555

56-
Now, when you navigate to a Service that has a SonarQube associated with it, you should be able to click on Plugins > SonarQube Issues and see the SonarQube Issues associated with the project that is linked to the service.
56+
### Create a plugin configuration entity (self-hosted only)
5757

58-
**Note: This plugin will connect to SonarQube's cloud instance out of the box.** If you are self-hosting SonarQube and need to direct the plugin to a different API endpoint, update the following section of the [SonarqubeIssues.tsx](src/components/SonarqubeIssues.tsx) file:
58+
This plugin will connect to SonarQube's cloud instance out of the box, so if you are using SonarQube in the cloud, you should skip this step. If you are self-hosting SonarQube and need to direct the plugin to a different REST API endpoint, create a plugin configuration entity with your SonarQube REST API base URL as follows:
59+
60+
- Consider creating a new entity type, so that any existing scorecards are not affected by this configuration entity. In this example, we have created a new entity type called `plugin-configuration`
61+
- Create a new entity with the tag `sonarqube-plugin-config`
62+
- Set `x-cortex-definition.sonarqube-url` to the value of your SonarQube API base URL. For example, if my SonarQube API base URL was `https://sonarqube.martindstone.com`, my `sonarqube-plugin-config` entity would look like this:
5963

60-
```ts
61-
// Set your SonarQube url. Cloud is https://sonarcloud.io
62-
const baseURL = "https://sonarcloud.io";
6364
```
65+
openapi: 3.0.1
66+
info:
67+
title: SonarQube Plugin Config
68+
description: ""
69+
x-cortex-tag: sonarqube-plugin-config
70+
x-cortex-type: plugin-configuration
71+
x-cortex-definition:
72+
sonarqube-url: https://sonarqube.martindstone.com
73+
```
74+
75+
Now, when you navigate to a Cortex service that has a SonarQube project associated with it, you should be able to click on Plugins > SonarQube Issues and see the SonarQube Issues associated with the project that is linked to the service.
6476

6577
## Troubleshooting
6678

plugins/sonarqube-issues/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
"version": "0.1.0",
44
"license": "MIT",
55
"dependencies": {
6+
"@chakra-ui/react": "2",
67
"@cortexapps/plugin-core": "^2.0.0",
8+
"@emotion/react": "^11.13.3",
9+
"@emotion/styled": "^11.13.0",
10+
"framer-motion": "^11.11.17",
711
"react": "^18.2.0",
812
"react-dom": "^18.2.0"
913
},

plugins/sonarqube-issues/src/components/App.tsx

Lines changed: 67 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type React from "react";
22
import { Box, PluginProvider } from "@cortexapps/plugin-core/components";
3+
import { ChakraProvider } from "@chakra-ui/react";
34
import "../baseStyles.css";
45
import ErrorBoundary from "./ErrorBoundary";
56
import CortexEntity from "./EntityInfo";
@@ -8,71 +9,73 @@ const App: React.FC = () => {
89
return (
910
<ErrorBoundary>
1011
<PluginProvider>
11-
<Box>
12-
<svg
13-
height="50"
14-
id="Logo"
15-
xmlns="http://www.w3.org/2000/svg"
16-
viewBox="0 0 796.79 292.01"
12+
<ChakraProvider toastOptions={{ defaultOptions: { position: "top" } }}>
13+
<Box>
14+
<svg
15+
height="50"
16+
id="Logo"
17+
xmlns="http://www.w3.org/2000/svg"
18+
viewBox="0 0 796.79 292.01"
19+
>
20+
<defs>
21+
<style>{`.cls-1{fill:#fd3456;}.cls-2{fill:#290042;}`}</style>
22+
</defs>
23+
<path
24+
className="cls-1"
25+
d="M203.35,135.27a102,102,0,0,0-7.23-38.16c-1,.41-1.72.79-2.24,1l0,0a5.86,5.86,0,0,0-3.13,5.93,141.71,141.71,0,0,1,.94,16c0,24.45-7.89,47.89-22.22,66-13.55,17.14-31.73,28.16-51.5,31.31l.17.1a40.28,40.28,0,0,0,37.65,1.13C183.69,204.94,203.35,172.73,203.35,135.27Z"
26+
/>
27+
<path
28+
className="cls-1"
29+
d="M208.8,94.62a27.7,27.7,0,0,0-5.18.33,109.86,109.86,0,0,1,7.51,40.32c0,42-23.4,79.27-57.56,92.86,1.72.11,3.46.17,5.21.17H159a54.8,54.8,0,0,0,42.41-20.38c13.08-16.2,21.11-38,21.11-61.91A100.35,100.35,0,0,0,208.8,94.62Z"
30+
/>
31+
<path
32+
className="cls-1"
33+
d="M241.08,146a82,82,0,0,0-6.27-31.56,36.25,36.25,0,0,0-7.91-12,26.37,26.37,0,0,0-6.21-4.66c-.58-.31-1.17-.58-1.75-.83a109.48,109.48,0,0,1,11.39,49c0,24.3-7.91,47.71-22,65.67A82.15,82.15,0,0,0,241.08,146Z"
34+
/>
35+
<path
36+
className="cls-2"
37+
d="M217.82,88.68a82.06,82.06,0,0,0-59-25c-45.48,0-82.76,37.67-82.29,83.15A81.92,81.92,0,0,0,83,178.23a22.19,22.19,0,0,0-4.08-.18c-3.69.17-8.91-1.17-11.27-1.83s-4.47,1.24-3.51,3.44l0,.06c8.17,18.72,26.28,30.9,43.57,30.86h0a32.89,32.89,0,0,0,3.44-.18c40.49-3.08,72.62-42.39,72.62-90.28,0-3-.13-6-.39-9a1.78,1.78,0,0,0-3.2-.92l0,0c-11.19,14.82-27.78,40.87-48.53,27.29-8-5.21-12.26-16.42-9.85-27.83,4.32-20.48,28.2-33.95,38.72-29.75.82.33,3.78,1.51,4.79,4.21,1.54,4.12-3.1,7.51-5.47,14.81-2.55,7.89-1.11,16.27.68,16.63,2,.41,5.35-6.93,13.61-13.59,6-4.84,10.52-6.2,13.36-11.32,2.74-5-2.14-10.27-.48-10.74s3.21,5.29,8.15,8.15c4.13,2.39,7.81.89,13.24.68a35.88,35.88,0,0,1,6,.46s1.07.14,2.75.49A.62.62,0,0,0,217.82,88.68Zm-61.34,63.44a5.8,5.8,0,0,1,3.74-2.27,4.79,4.79,0,0,1,3.69,1c2,1.84,1.41,5.43-.32,7.49-1.59,1.9-4.74,3.15-6.93,1.73a5,5,0,0,1-1.94-4A5.85,5.85,0,0,1,156.48,152.12Z"
38+
/>
39+
<path
40+
className="cls-2"
41+
d="M285.21,104.39s-17.63,0-17.63,17.64v20.1s0,17.64,17.63,17.64h48v20.1H287.17c-17.52,0-17.63,17.64-17.63,17.64h64.69s17.63,0,17.63-17.64v-20.1s0-17.64-17.63-17.64h-48V122h45.1c17.51,0,17.63-17.64,17.63-17.64H285.21Z"
42+
/>
43+
<path
44+
className="cls-2"
45+
d="M428.81,104.39h-49c-17.63,0-17.63,17.64-17.63,17.64v57.84c0,17.64,17.63,17.64,17.63,17.64h49c17.63,0,17.63-17.64,17.63-17.64V122C446.44,104.39,428.81,104.39,428.81,104.39Zm-1,75.48H380.77V122h47.06Z"
46+
/>
47+
<path
48+
className="cls-2"
49+
d="M457.72,105.37v91.16h18.62V122S476.34,105.37,457.72,105.37Z"
50+
/>
51+
<path
52+
className="cls-2"
53+
d="M524.37,104.39H494c-17.63,0-17.63,17.64-17.63,17.64h47.05v74.5H542V122C542,104.39,524.37,104.39,524.37,104.39Z"
54+
/>
55+
<path
56+
className="cls-2"
57+
d="M573.86,104.39H556.22c0,17.55,17.64,17.64,17.64,17.64H619v18.14h-48s-17.64,0-17.64,17.64v22.06s0,17.64,17.64,17.64h31.37s16.66,0,16.66-17.64H571.9v-22.8H619v22.8s.48,16.66,18.62,16.66V122s0-17.64-17.64-17.64Z"
58+
/>
59+
<path
60+
className="cls-2"
61+
d="M650.53,105.37v91.16h18.62V122C669.15,105.36,650.53,105.37,650.53,105.37Z"
62+
/>
63+
<path
64+
className="cls-2"
65+
d="M686.79,104.39c-17.64,0-17.64,17.64-17.64,17.64h46.07s17.64,0,17.64-17.64Z"
66+
/>
67+
</svg>
68+
</Box>
69+
<div
70+
style={{
71+
minHeight: "20em",
72+
height: "20em",
73+
maxHeight: "60vh",
74+
}}
1775
>
18-
<defs>
19-
<style>{`.cls-1{fill:#fd3456;}.cls-2{fill:#290042;}`}</style>
20-
</defs>
21-
<path
22-
className="cls-1"
23-
d="M203.35,135.27a102,102,0,0,0-7.23-38.16c-1,.41-1.72.79-2.24,1l0,0a5.86,5.86,0,0,0-3.13,5.93,141.71,141.71,0,0,1,.94,16c0,24.45-7.89,47.89-22.22,66-13.55,17.14-31.73,28.16-51.5,31.31l.17.1a40.28,40.28,0,0,0,37.65,1.13C183.69,204.94,203.35,172.73,203.35,135.27Z"
24-
/>
25-
<path
26-
className="cls-1"
27-
d="M208.8,94.62a27.7,27.7,0,0,0-5.18.33,109.86,109.86,0,0,1,7.51,40.32c0,42-23.4,79.27-57.56,92.86,1.72.11,3.46.17,5.21.17H159a54.8,54.8,0,0,0,42.41-20.38c13.08-16.2,21.11-38,21.11-61.91A100.35,100.35,0,0,0,208.8,94.62Z"
28-
/>
29-
<path
30-
className="cls-1"
31-
d="M241.08,146a82,82,0,0,0-6.27-31.56,36.25,36.25,0,0,0-7.91-12,26.37,26.37,0,0,0-6.21-4.66c-.58-.31-1.17-.58-1.75-.83a109.48,109.48,0,0,1,11.39,49c0,24.3-7.91,47.71-22,65.67A82.15,82.15,0,0,0,241.08,146Z"
32-
/>
33-
<path
34-
className="cls-2"
35-
d="M217.82,88.68a82.06,82.06,0,0,0-59-25c-45.48,0-82.76,37.67-82.29,83.15A81.92,81.92,0,0,0,83,178.23a22.19,22.19,0,0,0-4.08-.18c-3.69.17-8.91-1.17-11.27-1.83s-4.47,1.24-3.51,3.44l0,.06c8.17,18.72,26.28,30.9,43.57,30.86h0a32.89,32.89,0,0,0,3.44-.18c40.49-3.08,72.62-42.39,72.62-90.28,0-3-.13-6-.39-9a1.78,1.78,0,0,0-3.2-.92l0,0c-11.19,14.82-27.78,40.87-48.53,27.29-8-5.21-12.26-16.42-9.85-27.83,4.32-20.48,28.2-33.95,38.72-29.75.82.33,3.78,1.51,4.79,4.21,1.54,4.12-3.1,7.51-5.47,14.81-2.55,7.89-1.11,16.27.68,16.63,2,.41,5.35-6.93,13.61-13.59,6-4.84,10.52-6.2,13.36-11.32,2.74-5-2.14-10.27-.48-10.74s3.21,5.29,8.15,8.15c4.13,2.39,7.81.89,13.24.68a35.88,35.88,0,0,1,6,.46s1.07.14,2.75.49A.62.62,0,0,0,217.82,88.68Zm-61.34,63.44a5.8,5.8,0,0,1,3.74-2.27,4.79,4.79,0,0,1,3.69,1c2,1.84,1.41,5.43-.32,7.49-1.59,1.9-4.74,3.15-6.93,1.73a5,5,0,0,1-1.94-4A5.85,5.85,0,0,1,156.48,152.12Z"
36-
/>
37-
<path
38-
className="cls-2"
39-
d="M285.21,104.39s-17.63,0-17.63,17.64v20.1s0,17.64,17.63,17.64h48v20.1H287.17c-17.52,0-17.63,17.64-17.63,17.64h64.69s17.63,0,17.63-17.64v-20.1s0-17.64-17.63-17.64h-48V122h45.1c17.51,0,17.63-17.64,17.63-17.64H285.21Z"
40-
/>
41-
<path
42-
className="cls-2"
43-
d="M428.81,104.39h-49c-17.63,0-17.63,17.64-17.63,17.64v57.84c0,17.64,17.63,17.64,17.63,17.64h49c17.63,0,17.63-17.64,17.63-17.64V122C446.44,104.39,428.81,104.39,428.81,104.39Zm-1,75.48H380.77V122h47.06Z"
44-
/>
45-
<path
46-
className="cls-2"
47-
d="M457.72,105.37v91.16h18.62V122S476.34,105.37,457.72,105.37Z"
48-
/>
49-
<path
50-
className="cls-2"
51-
d="M524.37,104.39H494c-17.63,0-17.63,17.64-17.63,17.64h47.05v74.5H542V122C542,104.39,524.37,104.39,524.37,104.39Z"
52-
/>
53-
<path
54-
className="cls-2"
55-
d="M573.86,104.39H556.22c0,17.55,17.64,17.64,17.64,17.64H619v18.14h-48s-17.64,0-17.64,17.64v22.06s0,17.64,17.64,17.64h31.37s16.66,0,16.66-17.64H571.9v-22.8H619v22.8s.48,16.66,18.62,16.66V122s0-17.64-17.64-17.64Z"
56-
/>
57-
<path
58-
className="cls-2"
59-
d="M650.53,105.37v91.16h18.62V122C669.15,105.36,650.53,105.37,650.53,105.37Z"
60-
/>
61-
<path
62-
className="cls-2"
63-
d="M686.79,104.39c-17.64,0-17.64,17.64-17.64,17.64h46.07s17.64,0,17.64-17.64Z"
64-
/>
65-
</svg>
66-
</Box>
67-
<div
68-
style={{
69-
minHeight: "20em",
70-
height: "20em",
71-
maxHeight: "60vh",
72-
}}
73-
>
74-
<CortexEntity />
75-
</div>
76+
<CortexEntity />
77+
</div>
78+
</ChakraProvider>
7679
</PluginProvider>
7780
</ErrorBoundary>
7881
);

plugins/sonarqube-issues/src/components/SonarqubeIssues.test.tsx

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { render, screen, waitFor } from "@testing-library/react";
1+
import { render, waitFor } from "@testing-library/react";
22
import SonarqubeIssues from "./SonarqubeIssues";
33

44
const issuesResp = {
@@ -177,16 +177,16 @@ describe("Issues", () => {
177177
}
178178
);
179179

180-
render(<SonarqubeIssues entityYaml={serviceYaml} />);
181-
expect(screen.queryByText("Loading")).toBeInTheDocument();
180+
const { queryByText, queryAllByText } = render(
181+
<SonarqubeIssues entityYaml={serviceYaml} />
182+
);
182183
await waitFor(() => {
183-
expect(screen.queryByText("Loading")).not.toBeInTheDocument();
184+
expect(queryByText("Loading")).not.toBeInTheDocument();
185+
const majorElements = queryAllByText("major");
186+
expect(majorElements.length).toEqual(3);
187+
const commentElements = queryAllByText("Comment");
188+
expect(commentElements.length).toBeGreaterThan(0);
184189
});
185-
// expect(screen.queryByText("useless")).toBeInTheDocument();
186-
const majorElements = screen.queryAllByText("major");
187-
expect(majorElements.length).toEqual(3);
188-
const commentElements = screen.queryAllByText("Comment");
189-
expect(commentElements.length).toBeGreaterThan(0);
190190
});
191191

192192
it("has no Issues", async () => {
@@ -196,16 +196,17 @@ describe("Issues", () => {
196196
return await Promise.resolve(JSON.stringify({ issues: [] }));
197197
}
198198
);
199-
render(<SonarqubeIssues entityYaml={serviceYaml} />);
200-
expect(screen.queryByText("Loading")).toBeInTheDocument();
199+
const { queryByText } = render(
200+
<SonarqubeIssues entityYaml={serviceYaml} />
201+
);
201202

202203
await waitFor(() => {
203-
expect(screen.queryByText("Loading")).not.toBeInTheDocument();
204+
expect(queryByText("Loading")).not.toBeInTheDocument();
205+
expect(
206+
queryByText(
207+
"We could not find any Sonarqube issues associated with this entity"
208+
)
209+
).toBeInTheDocument();
204210
});
205-
expect(
206-
screen.queryByText(
207-
"We could not find any Sonarqube issues associated with this entity"
208-
)
209-
).toBeInTheDocument();
210211
});
211212
});

0 commit comments

Comments
 (0)