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

feat: expose plugin extension points into main package, developer docs + sample #713

Merged
merged 5 commits into from
Oct 21, 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
4 changes: 3 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
# This file required to override .gitignore when publishing to npm
# This file required to override .gitignore when publishing to npm
website/
plugins/
7 changes: 7 additions & 0 deletions config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
"description": "Flag to enable CSRF protections for UI",
"type": "boolean"
},
"plugins": {
"type": "array",
"description": "List of plugins to integrate on GitProxy's push or pull actions. Each value is either a file path or a module name.",
"items": {
"type": "string"
}
},
"authorisedList": {
"description": "List of repositories that are authorised to be pushed to through the proxy.",
"type": "array",
Expand Down
140 changes: 140 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
"git-proxy": "./index.js",
"git-proxy-all": "concurrently 'npm run server' 'npm run client'"
},
"exports": {
"./plugin": "./src/plugin.js",
"./proxy/actions": "./src/proxy/actions/index.js",
"./src/config/env": "./src/config/env.js"
},
"workspaces": [
"./packages/git-proxy-cli"
],
Expand Down Expand Up @@ -91,6 +96,7 @@
"mocha": "^10.2.0",
"nyc": "^17.0.0",
"prettier": "^3.0.0",
"sinon": "^19.0.2",
"vite": "^4.4.2"
},
"optionalDependencies": {
Expand Down
11 changes: 0 additions & 11 deletions packages/git-proxy-notify-hello/index.js

This file was deleted.

10 changes: 10 additions & 0 deletions plugins/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# GitProxy plugins & samples
GitProxy supports extensibility in the form of plugins. These plugins are specified via [configuration](/docs/category/configuration) as NPM packages or JavaScript code on disk. For each plugin configured, GitProxy will attempt to load each package or file as a standard [Node module](https://nodejs.org/api/modules.html). Plugin authors will create instances of the extension classes exposed by GitProxy and use these objects to implement custom functionality.

For detailed documentation, please refer to the [GitProxy development resources on the project's site](https://git-proxy.finos.org/docs/development/plugins)

## Included plugins
These plugins are maintained by the core GitProxy team. As a future roadmap item, organizations can choose to omit
certain features of GitProxy by simply removing the dependency from a deployed version of the application.

- `git-proxy-plugin-samples`: "hello world" examples of the GitProxy plugin system
45 changes: 45 additions & 0 deletions plugins/git-proxy-plugin-samples/example.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* This is a sample plugin that logs a message when the pull action is called. It is written using
* CommonJS modules to demonstrate the use of CommonJS in plugins.
*/

// Peer dependencies; its expected that these deps exist on Node module path if you've installed @finos/git-proxy
const { PushActionPlugin } = require('@finos/git-proxy/plugin');
const { Step } = require('@finos/git-proxy/proxy/actions');
'use strict';

/**
*
* @param {object} req Express Request object
* @param {Action} action GitProxy Action
* @return {Promise<Action>} Promise that resolves to an Action
*/
async function logMessage(req, action) {
const step = new Step('LogRequestPlugin');
action.addStep(step);
console.log(`LogRequestPlugin: req url ${req.url}`);
console.log(`LogRequestPlugin: req user-agent ${req.header('User-Agent')}`);
console.log('LogRequestPlugin: action', JSON.stringify(action));
return action;
}

class LogRequestPlugin extends PushActionPlugin {
constructor() {
super(logMessage)
}
}


module.exports = {
// Plugins can be written inline as new instances of Push/PullActionPlugin
// A custom class is not required
hello: new PushActionPlugin(async (req, action) => {
const step = new Step('HelloPlugin');
action.addStep(step);
console.log('Hello world from the hello plugin!');
return action;
}),
// Sub-classing is fine too if you require more control over the plugin
logRequest: new LogRequestPlugin(),
someOtherValue: 'foo', // This key will be ignored by the plugin loader
};
22 changes: 22 additions & 0 deletions plugins/git-proxy-plugin-samples/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* This is a sample plugin that logs a message when the pull action is called. It is written using
* ES modules to demonstrate the use of ESM in plugins.
*/

// Peer dependencies; its expected that these deps exist on Node module path if you've installed @finos/git-proxy
import { PullActionPlugin } from "@finos/git-proxy/plugin";
import { Step } from "@finos/git-proxy/proxy/actions";

class RunOnPullPlugin extends PullActionPlugin {
constructor() {
super(function logMessage(req, action) {
const step = new Step('RunOnPullPlugin');
action.addStep(step);
console.log('RunOnPullPlugin: Received fetch request', req.url);
return action;
})
}
}

// Default exports are supported and will be loaded by the plugin loader
export default new RunOnPullPlugin();
21 changes: 21 additions & 0 deletions plugins/git-proxy-plugin-samples/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@finos/git-proxy-plugin-samples",
"version": "0.1.0-alpha.0",
"description": "A set of sample (dummy) plugins for GitProxy to demonstrate how plugins are authored.",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Thomas Cooper",
"license": "Apache-2.0",
"type": "module",
"exports": {
".": "./index.js",
"./example": "./example.cjs"
},
"dependencies": {
"express": "^4.18.2"
},
"peerDependencies": {
"@finos/git-proxy": "1.3.5-alpha.5"
}
}
3 changes: 2 additions & 1 deletion proxy.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,6 @@
"privateOrganizations": [],
"urlShortener": "",
"contactEmail": "",
"csrfProtection": true
"csrfProtection": true,
"plugins": []
}
1 change: 0 additions & 1 deletion scripts/doc-schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ try {
console.log(genDocOutput);

const schemaDoc = readFileSync(`${tempdir}${sep}schema.md`, 'utf-8')
.replace(/\n\n<\/summary>/g, '</summary>')
.replace(/# GitProxy configuration file/g, '# Schema Reference'); // https://github.com/finos/git-proxy/pull/327#discussion_r1377343213
const docString = `---
title: Schema Reference
Expand Down
10 changes: 10 additions & 0 deletions src/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
let _sessionMaxAgeHours = defaultSettings.sessionMaxAgeHours;
let _sslKeyPath = defaultSettings.sslKeyPemPath;
let _sslCertPath = defaultSettings.sslCertPemPath;
let _plugins = defaultSettings.plugins;
let _commitConfig = defaultSettings.commitConfig;
let _attestationConfig = defaultSettings.attestationConfig;
let _privateOrganizations = defaultSettings.privateOrganizations;
Expand Down Expand Up @@ -160,6 +161,14 @@
return _csrfProtection;
};

// Get loadable push plugins
const getPlugins = () => {
if (_userSettings && _userSettings.plugins) {
_plugins = _userSettings.plugins;

Check warning on line 167 in src/config/index.js

View check run for this annotation

Codecov / codecov/patch

src/config/index.js#L166-L167

Added lines #L166 - L167 were not covered by tests
}
return _plugins;

Check warning on line 169 in src/config/index.js

View check run for this annotation

Codecov / codecov/patch

src/config/index.js#L169

Added line #L169 was not covered by tests
}

const getSSLKeyPath = () => {
if (_userSettings && _userSettings.sslKeyPemPath) {
_sslKeyPath = _userSettings.sslKeyPemPath;
Expand Down Expand Up @@ -195,5 +204,6 @@
exports.getURLShortener = getURLShortener;
exports.getContactEmail = getContactEmail;
exports.getCSRFProtection = getCSRFProtection;
exports.getPlugins = getPlugins;
exports.getSSLKeyPath = getSSLKeyPath;
exports.getSSLCertPath = getSSLCertPath;
Loading
Loading