Skip to content

PagerDuty incidents plugin #34

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

Merged
merged 5 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/pagerduty-incidents/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
dist/
29 changes: 29 additions & 0 deletions plugins/pagerduty-incidents/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
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",
},
settings: {
react: {
version: "detect",
},
},
};
12 changes: 12 additions & 0 deletions plugins/pagerduty-incidents/.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/pagerduty-incidents/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
dist/
89 changes: 89 additions & 0 deletions plugins/pagerduty-incidents/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# PagerDuty Incidents Cortex Plugin

View PagerDuty incidents associated with your services!!

<div align="center"><img src="img/pagerduty-incidents.png" /></div>

The PagerDuty Incidents plugin shows PagerDuty incidents associated with the PagerDuty service specified in the entity's `cortex.yaml`. If the `cortex.yaml` has a PagerDuty service defined in its `x-cortex-oncall` configuration, it will query for incidents in that service. For example:

```yaml
openapi: 3.0.1
info:
title: funrepo
description: Description of funrepo
x-cortex-tag: funrepo
x-cortex-type: service
x-cortex-oncall:
pagerduty:
id: PXXXXXX
type: SERVICE
```

## Setup

This plugin requires a proxy to PagerDuty. To set up:

- In PagerDuty, create an API Token by clicking on Integrations > API Access Keys > Create New API Key
- In Cortex, define a secret whose value is your new token. Name it `pagerduty_secret`.
- Create a plugin proxy in Cortex:

- Navigate to Plugins, then click on the Proxies tab, then click on Create Proxy
- Give the proxy a name, then click on Add URL
- For the URL Prefix, type in `https://api.pagerduty.com`
- Click on Add Header and add a header whose name is `Authorization` and whose value is `Token token={{{secrets.pagerduty_secret}}}` (include the curly braces!)

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

<div align="center"><img src="img/pagerduty-proxy.png"></div>

Now, you can build and add the plugin.

- Build the plugin:
- Make sure you have npm/yarn
- In your terminal, in the `pagerduty-incidents` directory, type `yarn` or `npm install` to install the dependencies
- Type `npm run build` or `yarn build` to build the plugin
- The compiled plugin will be created in `dist/ui.html`
- In Plugins > All, click **Register Plugin**
- Give the plugin a name, like PagerDuty Incidents. This is the name users will see in the plugin listing.
- Under **Associated Proxy**, choose the proxy you just created.
- Under **Plugin Context**, click on Add another context; choose Selection type: Include, and Entity types: service.
- This plugin does not work in the Global context. Turn off the switch labeled **Include in global context**
- In The **Plugin code** section, upload the `dist/ui.html` file you just built.
- Click on **Save plugin**

Now, when you navigate to a Cortex entity that has a PagerDuty oncall associated with it, you should be able to click on Plugins > PagerDuty Incidents and see the PagerDuty incidents associated with the service that is linked to the entity.

If no PagerDuty oncall is set for the entity, you will see a service chooser that allows you to map the entity to a PagerDuty service.

<div align="center"><img src="img/pagerduty-chooser.png"></div>

If you don't want to see the PagerDuty plugin at all on entities that don't have a PagerDuty oncall, then you can adjust the plugin visibility via CQL to only show in entities where `x-cortex-oncall.pagerduty.type = SERVICE`.

# Setting up your dev environment

PagerDuty Incidents 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/pagerduty-incidents/__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/pagerduty-incidents/__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/pagerduty-incidents/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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions plugins/pagerduty-incidents/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
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",
"^.+\\.js$": "babel-jest",
},
transformIgnorePatterns: [
"/node_modules/(?!yaml/)", // Add this line to tell Jest to transform `yaml` module
],
};
67 changes: 67 additions & 0 deletions plugins/pagerduty-incidents/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"name": "pagerduty-incidents-cortex-plugin",
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"@chakra-ui/react": "^2.10.2",
"@cortexapps/plugin-core": "^2.0.0",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"framer-motion": "^11.11.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"yaml": "^2.5.1"
},
"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/pagerduty-incidents/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/pagerduty-incidents/src/api/Cortex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const getEntityYaml = async (
baseUrl: string,
entityTag: string
): Promise<Record<string, any>> => {
const res = await fetch(`${baseUrl}/catalog/${entityTag}/openapi`);

return await res.json();
};
3 changes: 3 additions & 0 deletions plugins/pagerduty-incidents/src/baseStyles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
body {
font: 14px sans-serif;
}
Loading
Loading