Skip to content

Commit 192a237

Browse files
batzionbmareklibra
andauthored
chore(orchestrator): added script to enable the plugin in local setup of rhdh repo (#890)
* chore(orchestrator): added script to enable the plugin in local setup of rhdh repo * many improvements * Add scaffolder module and forms-widget to the export-to-rhdh-repo * added running yarn tsc --------- Co-authored-by: Marek Libra <marek.libra@gmail.com>
1 parent dbfeb0b commit 192a237

7 files changed

Lines changed: 325 additions & 2 deletions

File tree

workspaces/orchestrator/README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ For more information about audit logs in RHDH, please refer to [the official doc
211211

212212
The `orchestrator` plugin includes an extensible form for executing workflows. Details are available in the [extensible form documentation](./docs/extensibleForm.md).
213213

214-
## Contributors
214+
## Run locally from this repo
215215

216216
The orchestrator workspace is structured like a standard backstage application. To get it up and running locally run the following:
217217

@@ -224,3 +224,9 @@ yarn dev
224224
This will trigger a docker container run of devmode SonataFlow as described in [Devmode local configuration](#devmode-local-configuration).
225225

226226
More development guidelines available in the [contributors documentation](./docs/Contributors.md).
227+
228+
## Enable in rhdh repo locally
229+
230+
If you're running a local clone of [Red Hat Developer Hub (RHDH)](https://github.com/redhat-developer/rhdh) and want to use the Orchestrator plugin as a dynamic plugin, we've included a helper script to streamline this setup.
231+
232+
Please refer to the [Enabling the Orchestrator Plugin in rhdh repo locally](./workspaces/orchestrator/README.md#-enabling-the-orchestrator-plugin-in-red-hat-developer-hub) section for detailed instructions.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
## 🔌 Enabling the Orchestrator Plugin in rhdh repo locally
2+
3+
To enable the Orchestrator plugin in your [Red Hat Developer Hub (RHDH)](https://github.com/redhat-developer/rhdh) setup, run the following command from the workspaces/orchestrator directory:
4+
5+
```bash
6+
yarn enable-in-rhdh-repo
7+
```
8+
9+
This script will:
10+
11+
- Export both the frontend and backend of the plugin as dynamic plugins and copy the result to dynamic-plugins-root in rhdh repo.
12+
- Add the necessary configuration to your RHDH `app-config.local.yaml`. If it doesn’t exist, it copies a ready-to-use config from `scripts/config-for-rhdh-repo.yaml` — a better starting point than `app-config.example.yaml`, with defaults that work out of the box.
13+
- Avoid duplicate configuration if it's already present
14+
15+
### 📁 Required Directory Layout
16+
17+
The script assumes that your local clone of the RHDH repo is located **alongside** your `rhdh-plugins` (or equivalent) monorepo. Specifically:
18+
19+
```bash
20+
your-workspace/
21+
├── rhdh/ # Clone of https://github.com/redhat-developer/rhdh
22+
  └── dynamic-plugin-root/
23+
└── rhdh-plugins/ # This repo, where the orchestrator plugin lives
24+
  └── workspaces/
25+
    └── orchestrator/
26+
      ├── plugins/
27+
      │ ├── orchestrator/
28+
      │ └── orchestrator-backend/
29+
      └── enable-in-rhdh-repo.sh
30+
```
31+
32+
If you follow this layout, the script will work out of the box.
33+
If your RHDH repo is in a different location, you can override the path by setting the `RHDH_DIR` environment variable:
34+
35+
```bash
36+
RHDH_DIR=~/path/to/rhdh yarn enable-in-rhdh-repo
37+
```

workspaces/orchestrator/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"prettier:check": "prettier --check .",
2323
"prettier:fix": "prettier --write .",
2424
"new": "backstage-cli new --scope @red-hat-developer-hub",
25-
"postinstall": "./scripts/postinstall"
25+
"postinstall": "./scripts/postinstall",
26+
"enable-in-rhdh-repo": "node scripts/export-to-rhdh-repo.js && node scripts/update-config-in-rhdh-repo.js"
2627
},
2728
"workspaces": {
2829
"packages": [
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"root": true,
3+
"parserOptions": {
4+
"ecmaVersion": "latest"
5+
}
6+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
app:
2+
title: RHDH
3+
baseUrl: http://localhost:3001
4+
organization:
5+
name: My Org
6+
backend:
7+
baseUrl: http://localhost:7008
8+
listen:
9+
port: 7008
10+
csp:
11+
connect-src:
12+
- "'self'"
13+
- 'http:'
14+
- 'https:'
15+
cors:
16+
origin: http://localhost:3001
17+
credentials: true
18+
methods:
19+
- GET
20+
- HEAD
21+
- PATCH
22+
- POST
23+
- PUT
24+
- DELETE
25+
database:
26+
client: better-sqlite3
27+
connection: ':memory:'
28+
proxy:
29+
skipInvalidProxies: true
30+
endpoints: {}
31+
lighthouse:
32+
baseUrl: temp
33+
dynatrace:
34+
baseUrl: temp
35+
techdocs:
36+
builder: external
37+
auth:
38+
# see https://backstage.io/docs/auth/ to learn about auth providers
39+
environment: development
40+
providers:
41+
guest: {}
42+
gitlab:
43+
development:
44+
clientId: ${AUTH_GITLAB_CLIENT_ID}
45+
clientSecret: ${AUTH_GITLAB_CLIENT_SECRET}
46+
signIn:
47+
resolvers:
48+
- resolver: emailMatchingUserEntityProfileEmail
49+
# - resolver: usernameMatchingUserEntityName
50+
github:
51+
development:
52+
clientId: ${AUTH_GITHUB_CLIENT_ID}
53+
clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
54+
signIn:
55+
resolvers:
56+
- resolver: emailMatchingUserEntityProfileEmail
57+
catalog:
58+
import:
59+
entityFilename: catalog-info.yaml
60+
pullRequestBranchName: backstage-integration
61+
rules:
62+
- allow:
63+
- Component
64+
- System
65+
- Group
66+
- Resource
67+
- Location
68+
- Template
69+
- API
70+
locations:
71+
- type: file
72+
target: ../../catalog-entities/all.yaml
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/usr/bin/env node
2+
3+
const { spawnSync } = require('child_process');
4+
const path = require('path');
5+
const fs = require('fs');
6+
7+
const RHDH_DIR = process.env.RHDH_DIR
8+
? path.resolve(process.env.RHDH_DIR)
9+
: path.resolve(__dirname, '../../../..', 'rhdh');
10+
11+
const DYNAMIC_PLUGINS_ROOT = path.resolve(RHDH_DIR, 'dynamic-plugins-root');
12+
13+
const FRONTEND_PLUGIN = path.resolve(__dirname, '../plugins/orchestrator');
14+
const FRONTEND_WIDGETS_PLUGIN = path.resolve(
15+
__dirname,
16+
'../plugins/orchestrator-form-widgets',
17+
);
18+
const BACKEND_PLUGIN = path.resolve(
19+
__dirname,
20+
'../plugins/orchestrator-backend',
21+
);
22+
const BACKEND_SCAFFOLDER_MODULE_PLUGIN = path.resolve(
23+
__dirname,
24+
'../plugins/scaffolder-backend-module-orchestrator',
25+
);
26+
27+
function ensureDirExists(dir) {
28+
if (!fs.existsSync(dir)) {
29+
fs.mkdirSync(dir, { recursive: true });
30+
console.log(`📁 Created dynamic plugins root: ${dir}`);
31+
} else {
32+
console.log(`📁 Using dynamic plugins root: ${dir}`);
33+
}
34+
}
35+
36+
function exportPlugin(dir) {
37+
console.log(`🚀 Exporting plugin from ${dir}`);
38+
const result = spawnSync(
39+
'yarn',
40+
[
41+
'export-dynamic',
42+
'--dynamic-plugins-root',
43+
DYNAMIC_PLUGINS_ROOT,
44+
'--dev',
45+
'--clean',
46+
],
47+
{
48+
cwd: dir,
49+
stdio: 'inherit',
50+
shell: true,
51+
},
52+
);
53+
if (result.status !== 0) {
54+
console.error(`❌ Export failed for ${dir}`);
55+
process.exit(result.status);
56+
}
57+
}
58+
59+
function main() {
60+
if (!fs.existsSync(RHDH_DIR)) {
61+
console.error(`❌ RHDH repo not found at: ${RHDH_DIR}`);
62+
process.exit(1);
63+
}
64+
console.log('🛠️ Compiling TypeScript in workspaces/orchestrator');
65+
const tscResult = spawnSync('yarn', ['tsc'], {
66+
cwd: path.resolve(__dirname, '../'),
67+
stdio: 'inherit',
68+
shell: true,
69+
});
70+
71+
if (tscResult.status !== 0) {
72+
console.error('❌ TypeScript compilation failed.');
73+
process.exit(tscResult.status);
74+
}
75+
ensureDirExists(DYNAMIC_PLUGINS_ROOT);
76+
exportPlugin(FRONTEND_PLUGIN);
77+
exportPlugin(FRONTEND_WIDGETS_PLUGIN);
78+
exportPlugin(BACKEND_PLUGIN);
79+
exportPlugin(BACKEND_SCAFFOLDER_MODULE_PLUGIN);
80+
console.log('✅ Plugins exported.');
81+
}
82+
83+
main();
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/usr/bin/env node
2+
3+
const fs = require('fs');
4+
const path = require('path');
5+
const yaml = require('js-yaml');
6+
7+
const RHDH_DIR = process.env.RHDH_DIR
8+
? path.resolve(process.env.RHDH_DIR)
9+
: path.resolve(__dirname, '../../../..', 'rhdh');
10+
11+
const LOCAL_CONFIG = path.join(RHDH_DIR, 'app-config.local.yaml');
12+
const INITIAL_CONFIG = path.join(__dirname, 'config-for-rhdh-repo.yaml');
13+
14+
const pluginKey = 'red-hat-developer-hub.backstage-plugin-orchestrator';
15+
const widgetsPluginKey =
16+
'red-hat-developer-hub.backstage-plugin-orchestrator-form-widgets';
17+
18+
const orchestratorDynamicPlugins = {
19+
rootDirectory: 'dynamic-plugins-root',
20+
frontend: {
21+
[widgetsPluginKey]: {},
22+
[pluginKey]: {
23+
appIcons: [
24+
{
25+
name: 'orchestratorIcon',
26+
importName: 'OrchestratorIcon',
27+
},
28+
],
29+
dynamicRoutes: [
30+
{
31+
path: '/orchestrator',
32+
importName: 'OrchestratorPage',
33+
menuItem: {
34+
icon: 'orchestratorIcon',
35+
text: 'Orchestrator',
36+
},
37+
},
38+
],
39+
},
40+
},
41+
};
42+
43+
const orchestratorConfig = {
44+
sonataFlowService: {
45+
baseUrl: 'http://localhost',
46+
port: 8899,
47+
autoStart: true,
48+
workflowsSource: {
49+
gitRepositoryUrl:
50+
'https://github.com/rhdhorchestrator/backstage-orchestrator-workflows.git',
51+
localPath: path.resolve(
52+
__dirname,
53+
'../packages/backend/.devModeTemp/repository',
54+
),
55+
},
56+
},
57+
dataIndexService: {
58+
url: 'http://localhost:8899',
59+
},
60+
};
61+
62+
function createLocalConfigIfMissing() {
63+
if (!fs.existsSync(LOCAL_CONFIG)) {
64+
if (!fs.existsSync(INITIAL_CONFIG)) {
65+
console.error('❌ Missing app-config.example.yaml');
66+
process.exit(1);
67+
}
68+
fs.copyFileSync(INITIAL_CONFIG, LOCAL_CONFIG);
69+
console.log('📝 Created app-config.local.yaml from example');
70+
}
71+
}
72+
73+
function updateConfig() {
74+
const raw = fs.readFileSync(LOCAL_CONFIG, 'utf8');
75+
const config = yaml.load(raw) || {};
76+
77+
// Merge dynamicPlugins
78+
if (!config.dynamicPlugins) {
79+
config.dynamicPlugins = orchestratorDynamicPlugins;
80+
console.log('✅ Added dynamicPlugins section.');
81+
} else {
82+
config.dynamicPlugins.rootDirectory ??= 'dynamic-plugins-root';
83+
config.dynamicPlugins.frontend ??= {};
84+
85+
if (!config.dynamicPlugins.frontend[pluginKey]) {
86+
config.dynamicPlugins.frontend[pluginKey] =
87+
orchestratorDynamicPlugins.frontend[pluginKey];
88+
console.log(`✅ Added frontend plugin: ${pluginKey}`);
89+
}
90+
91+
if (!config.dynamicPlugins.frontend[widgetsPluginKey]) {
92+
config.dynamicPlugins.frontend[widgetsPluginKey] =
93+
orchestratorDynamicPlugins.frontend[widgetsPluginKey];
94+
console.log(`✅ Added frontend plugin: ${widgetsPluginKey}`);
95+
}
96+
}
97+
98+
// Merge orchestrator config
99+
config.orchestrator = {
100+
...(config.orchestrator || {}),
101+
...orchestratorConfig,
102+
};
103+
104+
const updated = yaml.dump(config, { lineWidth: -1 });
105+
fs.writeFileSync(LOCAL_CONFIG, updated, 'utf8');
106+
console.log(`✅ Updated ${LOCAL_CONFIG} with orchestrator config.`);
107+
}
108+
109+
function main() {
110+
if (!fs.existsSync(RHDH_DIR)) {
111+
console.error(`❌ RHDH repo not found at: ${RHDH_DIR}`);
112+
process.exit(1);
113+
}
114+
createLocalConfigIfMissing();
115+
updateConfig();
116+
}
117+
118+
main();

0 commit comments

Comments
 (0)