Skip to content

Commit 104bd3c

Browse files
committed
feat: expose plugin extension points into main package, developer docs + sample
- update PluginLoader to use load-plugin's native Node module resolution. this library already handles loading of files vs modules in node_modules/ so let's use that directly - add configuration-based plugin loading and deprecate environment variables - new documentation page for plugin development. loading, writing, etc. - add PullActionPlugin + unify config on just "plugins" - add explicit exports to make importing @finos/git-proxy more straight forward for plugins In addition, this commit adds both CommonJS and ES module examples of plugins and refactors them into a more reflective package. It also includes updates to the site documentation, specifically in the Development section, which now includes details about plugins and contribution guidelines. - fix issue with json-schema-for-humans producing bad output due to post-processing (script step no longer required) - docs: add section on docs on how to update the config schema + re-generate reference doc - fix: don't package website with git-proxy, update .npmignore on npm pack/publish
1 parent 661bdea commit 104bd3c

File tree

24 files changed

+1007
-151
lines changed

24 files changed

+1007
-151
lines changed

.npmignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
# This file required to override .gitignore when publishing to npm
1+
# This file required to override .gitignore when publishing to npm
2+
website/
3+
plugins/

config.schema.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@
3636
"description": "Flag to enable CSRF protections for UI",
3737
"type": "boolean"
3838
},
39+
"plugins": {
40+
"type": "array",
41+
"description": "List of plugins to integrate on Git Proxy's push or pull actions. Each value is either a file path or a module name.",
42+
"items": {
43+
"type": "string"
44+
}
45+
},
3946
"authorisedList": {
4047
"description": "List of repositories that are authorised to be pushed to through the proxy.",
4148
"type": "array",

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
"git-proxy": "./index.js",
2424
"git-proxy-all": "concurrently 'npm run server' 'npm run client'"
2525
},
26+
"exports": {
27+
"./plugin": "./src/plugin.js",
28+
"./proxy/actions": "./src/proxy/actions/index.js"
29+
},
2630
"workspaces": [
2731
"./packages/git-proxy-cli"
2832
],

packages/git-proxy-notify-hello/index.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

plugins/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Git Proxy plugins & samples
2+
Git Proxy 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, Git Proxy 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 Git Proxy and use these objects to implement custom functionality.
3+
4+
For detailed documentation, please refer to the [Git Proxy development resources on the project's site](https://git-proxy.finos.org/docs/development/plugins)
5+
6+
## Included plugins
7+
These plugins are maintained by the core Git Proxy team. As a future roadmap item, organizations can choose to omit
8+
certain features of Git Proxy by simply removing the dependency from a deployed version of the application.
9+
10+
- `git-proxy-plugin-samples`: "hello world" examples of the Git Proxy plugin system
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* This is a sample plugin that logs a message when the pull action is called. It is written using
3+
* CommonJS modules to demonstrate the use of CommonJS in plugins.
4+
*/
5+
6+
// Peer dependencies; its expected that these deps exist on Node module path if you've installed @finos/git-proxy
7+
const { PushActionPlugin } = require('@finos/git-proxy/plugin');
8+
const { Step } = require('@finos/git-proxy/proxy/actions');
9+
'use strict';
10+
11+
/**
12+
*
13+
* @param {object} req Express Request object
14+
* @param {Action} action Git Proxy Action
15+
* @return {Promise<Action>} Promise that resolves to an Action
16+
*/
17+
async function logMessage(req, action) {
18+
const step = new Step('LogRequestPlugin');
19+
action.addStep(step);
20+
console.log(`LogRequestPlugin: req url ${req.url}`);
21+
console.log(`LogRequestPlugin: req user-agent ${req.header('User-Agent')}`);
22+
console.log('LogRequestPlugin: action', JSON.stringify(action));
23+
return action;
24+
}
25+
26+
class LogRequestPlugin extends PushActionPlugin {
27+
constructor() {
28+
super(logMessage)
29+
}
30+
}
31+
32+
33+
module.exports = {
34+
// Plugins can be written inline as new instances of Push/PullActionPlugin
35+
// A custom class is not required
36+
hello: new PushActionPlugin(async (req, action) => {
37+
const step = new Step('HelloPlugin');
38+
action.addStep(step);
39+
console.log('Hello world from the hello plugin!');
40+
return action;
41+
}),
42+
// Sub-classing is fine too if you require more control over the plugin
43+
logRequest: new LogRequestPlugin(),
44+
someOtherValue: 'foo', // This key will be ignored by the plugin loader
45+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* This is a sample plugin that logs a message when the pull action is called. It is written using
3+
* ES modules to demonstrate the use of ESM in plugins.
4+
*/
5+
6+
// Peer dependencies; its expected that these deps exist on Node module path if you've installed @finos/git-proxy
7+
import { PullActionPlugin } from "@finos/git-proxy/plugin";
8+
import { Step } from "@finos/git-proxy/proxy/actions";
9+
10+
class RunOnPullPlugin extends PullActionPlugin {
11+
constructor() {
12+
super(function logMessage(req, action) {
13+
const step = new Step('RunOnPullPlugin');
14+
action.addStep(step);
15+
console.log('RunOnPullPlugin: Received fetch request', req.url);
16+
return action;
17+
})
18+
}
19+
}
20+
21+
// Default exports are supported and will be loaded by the plugin loader
22+
export default new RunOnPullPlugin();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "@finos/git-proxy-plugin-samples",
3+
"version": "0.1.0-alpha.0",
4+
"description": "A set of sample (dummy) plugins for Git Proxy to demonstrate how plugins are authored.",
5+
"scripts": {
6+
"test": "echo \"Error: no test specified\" && exit 1"
7+
},
8+
"author": "Thomas Cooper",
9+
"license": "Apache-2.0",
10+
"type": "module",
11+
"exports": {
12+
".": "./index.js",
13+
"./example": "./example.cjs"
14+
},
15+
"dependencies": {
16+
"express": "^4.18.2"
17+
},
18+
"peerDependencies": {
19+
"@finos/git-proxy": "1.3.5-alpha.5"
20+
}
21+
}

scripts/doc-schema.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ try {
2020
console.log(genDocOutput);
2121

2222
const schemaDoc = readFileSync(`${tempdir}${sep}schema.md`, 'utf-8')
23-
.replace(/\n\n<\/summary>/g, '</summary>')
2423
.replace(/# GitProxy configuration file/g, '# Schema Reference'); // https://github.com/finos/git-proxy/pull/327#discussion_r1377343213
2524
const docString = `---
2625
title: Schema Reference

src/config/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ let _cookieSecret = defaultSettings.cookieSecret;
1717
let _sessionMaxAgeHours = defaultSettings.sessionMaxAgeHours;
1818
let _sslKeyPath = defaultSettings.sslKeyPemPath;
1919
let _sslCertPath = defaultSettings.sslCertPemPath;
20+
let _plugins = defaultSettings.plugins;
2021
let _commitConfig = defaultSettings.commitConfig;
2122
let _attestationConfig = defaultSettings.attestationConfig;
2223
let _privateOrganizations = defaultSettings.privateOrganizations;
@@ -160,6 +161,14 @@ const getCSRFProtection = () => {
160161
return _csrfProtection;
161162
};
162163

164+
// Get loadable push plugins
165+
const getPlugins = () => {
166+
if (_userSettings && _userSettings.plugins) {
167+
_plugins = _userSettings.plugins;
168+
}
169+
return _plugins;
170+
}
171+
163172
const getSSLKeyPath = () => {
164173
if (_userSettings && _userSettings.sslKeyPemPath) {
165174
_sslKeyPath = _userSettings.sslKeyPemPath;
@@ -195,5 +204,6 @@ exports.getPrivateOrganizations = getPrivateOrganizations;
195204
exports.getURLShortener = getURLShortener;
196205
exports.getContactEmail = getContactEmail;
197206
exports.getCSRFProtection = getCSRFProtection;
207+
exports.getPlugins = getPlugins;
198208
exports.getSSLKeyPath = getSSLKeyPath;
199209
exports.getSSLCertPath = getSSLCertPath;

0 commit comments

Comments
 (0)