Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GitLab Issues Plugin #11

Merged
merged 39 commits into from
Oct 28, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
36df081
Initial Commit
Aug 14, 2023
3621bab
First commit of plugin, still needs work
Aug 14, 2023
6e7256d
Added Readme, issues now show in ascending order
Aug 15, 2023
57db196
Increased size of images in readme
Aug 15, 2023
219177b
Added Loader logic & logic to show user if no issues found
Aug 18, 2023
1ce84a2
Added basic tests
Sep 5, 2023
4e4f468
ran git fetch && git merge origin/master and updated yarn.lock
Oct 9, 2023
561af97
added tests
Oct 15, 2023
c403932
removed cortex.yaml
Oct 23, 2023
13782a2
removed logo.svg
Oct 23, 2023
9f3e409
removed unused function getCortexContext from cortex.ts file and ran …
Oct 23, 2023
4b24f24
updates from PR Review
Oct 24, 2023
7cad0fa
Update plugins/gitlab-issues-plugin/src/components/Issues.tsx
cremerfc Oct 24, 2023
e5a3456
Update plugins/gitlab-issues-plugin/src/components/Issues.tsx
cremerfc Oct 24, 2023
6ae3e1c
Update plugins/gitlab-issues-plugin/src/components/Issues.tsx
cremerfc Oct 24, 2023
d27b204
Update plugins/gitlab-issues-plugin/src/components/Issues.test.tsx
cremerfc Oct 24, 2023
545aaf1
more changes from PR
Oct 24, 2023
1f6b824
adding more tests
Oct 24, 2023
5c5af14
fix tests
FoodProduct Oct 24, 2023
d75dbfb
renamed plugin folder
Oct 24, 2023
be4813d
removed PluginContext and updated ReadMe
Oct 25, 2023
907e530
removed jest dependency in run time
Oct 25, 2023
e2feb86
ran yarn fix
Oct 25, 2023
d17569d
Update plugins/gitlab-issues/src/components/EntityInfo.test.tsx
cremerfc Oct 25, 2023
f1cf7ff
Update plugins/gitlab-issues/src/api/Cortex.ts
cremerfc Oct 25, 2023
e6ed92a
Update plugins/gitlab-issues/src/components/Issues.tsx
cremerfc Oct 25, 2023
e565318
Update plugins/gitlab-issues/src/lib/parseEntity.ts
cremerfc Oct 25, 2023
8d5c91f
Update plugins/gitlab-issues/src/lib/parseEntity.ts
cremerfc Oct 25, 2023
b5d5c61
resolved issues with tests introduced by committing changes from revi…
Oct 25, 2023
f941fbd
ran yarn fix
Oct 25, 2023
31dc53b
simplify parseEntity
FoodProduct Oct 25, 2023
c7ae42d
Added instructions for self hosted GitLab to ReadMe
Oct 26, 2023
7a44bf8
Update plugins/gitlab-issues/README.md
cremerfc Oct 27, 2023
319b5ab
Update plugins/gitlab-issues/README.md
cremerfc Oct 27, 2023
9bb9ed7
Update plugins/gitlab-issues/src/components/Issues.tsx
cremerfc Oct 27, 2023
074bd41
Update plugins/gitlab-issues/README.md
cremerfc Oct 27, 2023
7848d54
ran yarn fix after PR commits
Oct 27, 2023
62c3080
small grammar correction
Oct 28, 2023
590c3a2
copy cleanup
FoodProduct Oct 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions plugins/gitlab-issues-plugin/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
dist/
30 changes: 30 additions & 0 deletions plugins/gitlab-issues-plugin/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
"standard-with-typescript",
"prettier",
],
overrides: [],
parserOptions: {
ecmaVersion: "latest",
project: "tsconfig.json",
sourceType: "module",
tsconfigRootDir: __dirname,
},
plugins: ["react"],
rules: {
// conflicts with no-extra-boolean-cast
"@typescript-eslint/strict-boolean-expressions": "off",
"no-console": ["error", { allow: ["warn", "error"] }],
},
settings: {
react: {
version: "detect",
},
},
};
12 changes: 12 additions & 0 deletions plugins/gitlab-issues-plugin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# OSX
*.DS_Store

# IDEs
.idea
*.iml
.vscode

# This project
node_modules/
dist/
yarn-error.log
2 changes: 2 additions & 0 deletions plugins/gitlab-issues-plugin/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
dist/
62 changes: 62 additions & 0 deletions plugins/gitlab-issues-plugin/README.md
cremerfc marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# GitLab Issues Cortex Plugin

View GitLab Issues associated to your services!
cremerfc marked this conversation as resolved.
Show resolved Hide resolved

<div align="center"><img src="img/gl-issues-cortex.png" width="650" /></div>

The GitLab Issues shows the open GitLab issues associated to the GitLab repository specified in the entity's `cortex.yaml`. If the `cortex.yaml` has a `basepath` defined in its `x-cortex-git` configuration, it will query for issues filtering by a label that matches the tag of the entity.

## Setup

This plugin requires a proxy to GitLab. The API that the plugin uses is documented [here](https://docs.gitlab.com/ee/api/issues.html), which details the type of headers you need defined.

- Define a secret that contains your GitLab Access Token. To determine which type of token to use, check the [docs](https://docs.gitlab.com/ee/api/rest/index.html#authentication).
- Define a proxy that is pointed to your GitHub instance with the headers mentioned in the docs. Here is a screenshot of how your proxy may look like:
cremerfc marked this conversation as resolved.
Show resolved Hide resolved
<div align="center"><img src="img/gl-proxy.png" width="600" /></div>

- Register the plugin.
- This plan will not work on the Global context.
- Select the entity that will have the GitHub repo in its `cortex.yaml`

## Troubleshooting

### Getting a message that "This service does not have a GitLab Repo defined"

If you get the following message:

<div align="center"><img src="img/gl-no-repo-defined.png" width="640" /></div>

This means that the plugin did not find a GitHub repository defined as described [here](https://docs.cortex.io/docs/reference/integrations/github#catalog-descriptor).

### Getting a generic error message

If you are getting a generic "Oops! There was a runtime error" message, you may want to look the browser's console and track where the plugin is breaking down based on which `console.log` output is displayed in the console.
cremerfc marked this conversation as resolved.
Show resolved Hide resolved

# Setting up your dev environment

GitLab Issues Plugin is a [Cortex](https://www.cortex.io/) plugin. To see how to run the plugin inside of Cortex, see [our docs](https://docs.cortex.io/docs/plugins).

### Prerequisites

Developing and building this plugin requires either [yarn](https://classic.yarnpkg.com/lang/en/docs/install/) or [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).

## Getting started

1. Run `yarn` or `npm install` to download all dependencies
2. Run `yarn build` or `npm run build` to compile the plugin code into `./dist/ui.html`
3. Upload `ui.html` into Cortex on a create or edit plugin page
4. Add or update the code and repeat steps 2-3 as necessary

### Notable scripts

The following commands come pre-configured in this repository. You can see all available commands in the `scripts` section of [package.json](./package.json). They can be run with npm via `npm run {script_name}` or with yarn via `yarn {script_name}`, depending on your package manager preference. For instance, the `build` command can be run with `npm run build` or `yarn build`.

- `build` - compiles the plugin. The compiled code root is `./src/index.tsx` (or as defined by [webpack.config.js](webpack.config.js)) and the output is generated into `dist/ui.html`.
- `test` - runs all tests defined in the repository using [jest](https://jestjs.io/)
- `lint` - runs lint and format checking on the repository using [prettier](https://prettier.io/) and [eslint](https://eslint.org/)
- `lintfix` - runs eslint in fix mode to fix any linting errors that can be fixed automatically
- `formatfix` - runs Prettier in fix mode to fix any formatting errors that can be fixed automatically

### Available React components

See available UI components via our [Storybook](https://cortexapps.github.io/plugin-core/).
1 change: 1 addition & 0 deletions plugins/gitlab-issues-plugin/__mocks__/fileMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = "test-file-stub";
1 change: 1 addition & 0 deletions plugins/gitlab-issues-plugin/__mocks__/styleMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = {};
8 changes: 8 additions & 0 deletions plugins/gitlab-issues-plugin/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
plugins: ["@babel/plugin-syntax-jsx"],
presets: [
["@babel/preset-env", { targets: { node: "current" } }],
"@babel/preset-typescript",
["@babel/preset-react", { runtime: "automatic" }],
],
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/gitlab-issues-plugin/img/gl-proxy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions plugins/gitlab-issues-plugin/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
moduleNameMapper: {
// map static asset imports to a stub file under the assumption they are not important to our tests
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/__mocks__/fileMock.js",
// map style asset imports to a stub file under the assumption they are not important to our tests
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
"@cortexapps/plugin-core/components":
"<rootDir>/../../node_modules/@cortexapps/plugin-core/dist/components.cjs.js",
"@cortexapps/plugin-core":
"<rootDir>/../../node_modules/@cortexapps/plugin-core/dist/index.cjs.js",
},
setupFilesAfterEnv: ["<rootDir>/setupTests.ts"],
testEnvironment: "jsdom",
transform: {
"^.+\\.tsx?$": "babel-jest",
},
};
63 changes: 63 additions & 0 deletions plugins/gitlab-issues-plugin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"name": "GitLabIssuesPlugin",
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"@cortexapps/plugin-core": "^2.0.0",
"jest": "^29.7.0",
cremerfc marked this conversation as resolved.
Show resolved Hide resolved
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@babel/core": "^7.21.3",
"@babel/plugin-syntax-jsx": "^7.18.6",
"@babel/preset-env": "^7.20.2",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.21.0",
"@popperjs/core": "^2.11.8",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.0.0",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.55.0",
"babel-jest": "^29.5.0",
"css-loader": "^6.7.3",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.7.0",
"eslint-config-standard-with-typescript": "^34.0.0",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-n": "^15.6.1",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"html-webpack-plugin": "^5.5.0",
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"jest-fetch-mock": "^3.0.3",
"npm-run-all": "^4.1.5",
"prettier": "^2.8.4",
"prop-types": "^15.8.1",
"react-dev-utils": "^12.0.1",
"style-loader": "^3.3.1",
"terser-webpack-plugin": "^5.3.7",
"ts-loader": "^9.4.2",
"typescript": "^4.9.5",
"url-loader": "^4.1.1",
"webpack": "^5.76.1",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.15.0"
},
"scripts": {
"build": "webpack --mode=production",
"clean": "rm -r ./dist",
"dev": "webpack serve --mode=development",
"fix": "run-p formatfix lintfix",
"formatfix": "yarn prettier . --write",
"formatcheck": "yarn prettier . --check",
"lint": "run-p formatcheck lintcheck",
"lintcheck": "yarn eslint src",
"lintfix": "yarn lintcheck --fix",
"test": "jest"
}
}
60 changes: 60 additions & 0 deletions plugins/gitlab-issues-plugin/setupTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import "@testing-library/jest-dom/extend-expect";
import fetchMock from "jest-fetch-mock";

fetchMock.enableMocks();

const mockContext = {
apiBaseUrl: "https://api.getcortexapp.com",
entity: {
definition: null,
description: null,
groups: null,
name: "Inventory planner",
ownership: {
emails: [
{
description: null,
email: "[email protected]",
inheritance: null,
id: 1,
},
],
},
tag: "inventory-planner",
type: "service",
},
location: "ENTITY",
user: {
email: "[email protected]",
name: "Ganesh Datta",
role: "ADMIN",
},
};

jest.mock("@cortexapps/plugin-core/components", () => {
const originalModule = jest.requireActual(
"@cortexapps/plugin-core/components"
);
return {
...originalModule,
usePluginContext: () => {
return mockContext;
},
PluginProvider: ({ children }) => {
return children;
},
};
});

jest.mock("@cortexapps/plugin-core", () => {
const originalModule = jest.requireActual("@cortexapps/plugin-core");
return {
...originalModule,
CortexApi: {
...originalModule.CortexApi,
getContext: () => {
return mockContext;
},
},
};
});
8 changes: 8 additions & 0 deletions plugins/gitlab-issues-plugin/src/api/Cortex.ts
cremerfc marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const getEntityYaml = async (
baseUrl: string,
entityTag: string
): Promise<any> => {
const res = await fetch(`${baseUrl}/catalog/${entityTag}/openapi`);

return await res.json();
};
3 changes: 3 additions & 0 deletions plugins/gitlab-issues-plugin/src/baseStyles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
body {
font: 14px sans-serif;
}
22 changes: 22 additions & 0 deletions plugins/gitlab-issues-plugin/src/components/App.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { render, screen, waitFor } from "@testing-library/react";
import App from "./App";

fetchMock.mockResponse(
JSON.stringify({
value:
"https://docs.google.com/forms/d/e/1FAIpQLSd068wYDvfxbhB75fTx-KM7aWb9gNiLLcnjA6SQ4ulT9SLgqA/viewform?embedded=true",
})
);
describe("App", () => {
it("verifies that the plugin works", async () => {
render(<App />);

expect(fetch).toHaveBeenCalledWith(
"https://api.getcortexapp.com/catalog/inventory-planner/openapi"
);

await waitFor(() => {
expect(screen.queryByText("Loading")).not.toBeInTheDocument();
});
});
});
25 changes: 25 additions & 0 deletions plugins/gitlab-issues-plugin/src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type React from "react";
import { Box, Title, PluginProvider } from "@cortexapps/plugin-core/components";
import "../baseStyles.css";
import ErrorBoundary from "./ErrorBoundary";
import CortexEntity from "./EntityInfo";

const App: React.FC = () => {
return (
<ErrorBoundary>
<PluginProvider>
<Box>
<img
src="https://about.gitlab.com/images/press/logo/png/gitlab-logo-500.png"
width="100"
height="100"
/>
<Title level={1}>GitLab Issues</Title>
</Box>
<CortexEntity />
</PluginProvider>
</ErrorBoundary>
);
};

export default App;
24 changes: 24 additions & 0 deletions plugins/gitlab-issues-plugin/src/components/EntityInfo.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { render, screen, waitFor } from "@testing-library/react";
import EntityInfo from "./EntityInfo";

describe("EntityInfo", () => {
it("Shows message when no GitLab info found", async () => {
fetchMock.mockIf(
/^https:\/\/api\.getcortexapp\.com\/catalog\/.*/,
async (_req: Request) => {
return await Promise.resolve(
JSON.stringify({
info: {},
})
);
}
);
render(<EntityInfo />);

await waitFor(() => {
expect(
screen.queryByText("No GitLab details were found for this entity")
).toBeInTheDocument();
});
});
});
Loading
Loading