Files
api/plugin/builder/build-plugin.ts
Eli Bosley d63e54bdbc feat: split plugin builds
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced containerized plugin deployment support with updated Docker
Compose configurations.
- Added continuous build watch modes for API, web, and UI components for
smoother development iterations.
  - Added a new job for API testing in the CI/CD workflow.
- Added a new shell script to determine the local host's IP address for
Docker configurations.
- Introduced a new entry point and HTTP server setup in the plugin's
Docker environment.
- Added new scripts for building and watching plugin changes in
real-time.
- Added a new script for building the project in watch mode for the API
and UI components.

- **Improvements**
- Streamlined the plugin installation process and refined release
workflows for a more reliable user experience.
- Enhanced overall CI/CD pipelines to ensure efficient, production-ready
deployments.
- Updated artifact upload paths and job definitions for clarity and
efficiency.
- Implemented new utility functions for better URL management and
changelog generation.
- Modified the `.dockerignore` file to ignore all contents within the
`node_modules` directory.
- Added new constants and functions for managing plugin paths and
configurations.
- Updated the build process in the Dockerfile to focus on release
operations.

- **Tests**
- Expanded automated testing to validate environment setups and build
stability, ensuring higher reliability during updates.
- Introduced new test suites for validating plugin environment setups
and configurations.
- Added tests for validating environment variables and handling of
manifest files.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Datelle <mdatelle@icloud.com>
Co-authored-by: mdatelle <mike@datelle.net>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Pujit Mehrotra <pujit@lime-technology.com>
2025-03-04 15:18:04 -05:00

109 lines
3.0 KiB
TypeScript

import { readFile, writeFile, mkdir, rename } from "fs/promises";
import { $ } from "zx";
import { escape as escapeHtml } from "html-sloppy-escaper";
import { dirname, join } from "node:path";
import { getTxzName, pluginName, startingDir } from "./utils/consts";
import { getPluginUrl } from "./utils/bucket-urls";
import { getMainTxzUrl } from "./utils/bucket-urls";
import {
deployDir,
getDeployPluginPath,
getRootPluginPath,
} from "./utils/paths";
import { PluginEnv, setupPluginEnv } from "./cli/setup-plugin-environment";
import { cleanupPluginFiles } from "./utils/cleanup";
/**
* Check if git is available
*/
const checkGit = async () => {
try {
await $`git log -1 --pretty=%B`;
} catch (err) {
console.error(`Error: git not available: ${err}`);
throw new Error(`Git not available: ${err}`);
}
};
const moveTxzFile = async (txzPath: string, pluginVersion: string) => {
const txzName = getTxzName(pluginVersion);
await rename(txzPath, join(deployDir, txzName));
};
function updateEntityValue(
xmlString: string,
entityName: string,
newValue: string
) {
console.log("Updating entity:", entityName, "with value:", newValue);
const regex = new RegExp(`<!ENTITY ${entityName} "[^"]*">`);
if (regex.test(xmlString)) {
return xmlString.replace(regex, `<!ENTITY ${entityName} "${newValue}">`);
}
throw new Error(`Entity ${entityName} not found in XML`);
}
const buildPlugin = async ({
pluginVersion,
baseUrl,
tag,
txzSha256,
releaseNotes,
}: PluginEnv) => {
// Update plg file
let plgContent = await readFile(getRootPluginPath({ startingDir }), "utf8");
// Update entity values
const entities: Record<string, string> = {
name: pluginName,
version: pluginVersion,
pluginURL: getPluginUrl({ baseUrl, tag }),
MAIN_TXZ: getMainTxzUrl({ baseUrl, pluginVersion, tag }),
TXZ_SHA256: txzSha256,
...(tag ? { TAG: tag } : {}),
};
console.log("Entities:", entities);
// Iterate over entities and update them
Object.entries(entities).forEach(([key, value]) => {
if (!value) {
throw new Error(`Entity ${key} not set in entities: ${JSON.stringify(entities)}`);
}
plgContent = updateEntityValue(plgContent, key, value);
});
if (releaseNotes) {
// Update the CHANGES section with release notes
plgContent = plgContent.replace(
/<CHANGES>.*?<\/CHANGES>/s,
`<CHANGES>\n${escapeHtml(releaseNotes)}\n</CHANGES>`
);
}
await mkdir(dirname(getDeployPluginPath({ startingDir })), {
recursive: true,
});
console.log("Writing plg file to:", getDeployPluginPath({ startingDir }));
await writeFile(getDeployPluginPath({ startingDir }), plgContent);
};
/**
* Main build script
*/
const main = async () => {
try {
const validatedEnv = await setupPluginEnv(process.argv);
await checkGit();
await cleanupPluginFiles();
await buildPlugin(validatedEnv);
await moveTxzFile(validatedEnv.txzPath, validatedEnv.pluginVersion);
} catch (error) {
console.error(error);
process.exit(1);
}
};
await main();