@starship-ci/generator
Version:
Kubernetes manifest generator for Starship deployments
83 lines (82 loc) • 3.63 kB
JavaScript
import * as fs from 'fs';
import * as yaml from 'js-yaml';
import * as path from 'path';
import { applyDefaults } from '../defaults';
import { ChainBuilder } from './chains';
import { ExplorerBuilder } from './explorer';
import { FrontendBuilder } from './frontend';
import { IngressBuilder } from './ingress';
import { MonitoringBuilder } from './monitoring';
import { RegistryBuilder } from './registry';
import { RelayerBuilder } from './relayers';
export class BuilderManager {
config;
constructor(config) {
this.config = applyDefaults(config);
}
getManifestOutputPath(manifest, baseDir) {
const labels = manifest.metadata?.labels || {};
const component = labels['app.kubernetes.io/component'];
const partOf = labels['app.kubernetes.io/part-of'];
const role = labels['app.kubernetes.io/role'];
const kind = manifest.kind.toLowerCase();
const name = manifest.metadata.name;
if (component === 'chain') {
// Chain-specific resources: outputs/<chain-name>/<role>-<kind>.yaml
// For StatefulSets, use the special chain-name label, otherwise use app.kubernetes.io/name
const chainName = labels['starship.io/chain-name'] || labels['app.kubernetes.io/name'];
const roleType = role || 'default'; // genesis, validator, setup-scripts, genesis-patch, ics-proposal
return path.join(baseDir, chainName, `${roleType}-${kind}.yaml`);
}
else if (partOf === 'global') {
// Global configmaps: outputs/configmaps/<clean-name>.yaml (remove redundant suffixes)
const cleanName = name.replace(/-?configmap$/, ''); // Remove -configmap or configmap suffix
return path.join(baseDir, 'configmaps', `${cleanName}.yaml`);
}
else if (component) {
// Component resources: outputs/<component>/<clean-kind>.yaml (remove redundant prefixes)
const cleanName = name.replace(new RegExp(`^${component}-?`), ''); // Remove component prefix
const fileName = cleanName ? `${cleanName}-${kind}.yaml` : `${kind}.yaml`;
return path.join(baseDir, component, fileName);
}
else {
// Fallback: outputs/<name>-<kind>.yaml
return path.join(baseDir, `${name}-${kind}.yaml`);
}
}
writeManifestToPath(manifest, filePath) {
// Ensure directory exists
const dir = path.dirname(filePath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
// Write YAML file
fs.writeFileSync(filePath, yaml.dump(manifest));
}
writeManifests(manifests, outputDir) {
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
manifests.forEach((manifest) => {
const outputPath = this.getManifestOutputPath(manifest, outputDir);
this.writeManifestToPath(manifest, outputPath);
});
}
build(outputDir) {
const builders = [
new ChainBuilder(this.config),
new RegistryBuilder(this.config),
new ExplorerBuilder(this.config),
new FrontendBuilder(this.config),
new RelayerBuilder(this.config),
new IngressBuilder(this.config),
new MonitoringBuilder(this.config)
];
let allManifests = [];
builders.forEach((builder) => {
allManifests = allManifests.concat(builder.generate());
});
this.writeManifests(allManifests, outputDir);
return allManifests;
}
}