mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
* fix: release.yml * fix: S3ChannelConfigSchema type port mismatch * fix(csp): Conditionally sets UPGRADE_INSECURE_REQUESTS based on the PROJECT_URL scheme. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: fix bug in github action. * chore: adding e2e tesing for notification. * fix: updating trivy-action to the latest version, using new tagging pattern (vX.XX.XX instead of (X.XX.XX). * fix: removing browser targeting in e2e workflow as it is already specify in playwright.config.ts * fix: mapping secrets to environment variables in the end-to-end workflow. * fix: add a condition to allow end-to-end workflow execution only on main repo (fork are excluded). * fix: adding some data-testid to rely on more stable locator. * fix: adding some data-testid to rely on more stable locator. * fix: removing unusued browsers in end-to-end workflow. * fix: removing unused browsers in end-to-end workflow. * fix: removing unused browsers in end-to-end workflow. --------- Co-authored-by: charlesgauthereau <charles.gauthereau@soluce-technologies.com> Co-authored-by: killianlarcher <killian.larcher@soluce-technologies.com>
108 lines
3.4 KiB
TypeScript
108 lines
3.4 KiB
TypeScript
import * as pty from "node-pty";
|
|
|
|
type InteractiveStep = {
|
|
match: RegExp;
|
|
reply: string;
|
|
};
|
|
|
|
function normalizeOutput(output: string) {
|
|
return output.replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, "");
|
|
}
|
|
|
|
/**
|
|
* Run an interactive CLI command and answer prompts in sequence.
|
|
* Entry point:
|
|
* - `command` is the full CLI command executed in the PTY.
|
|
* - `cwd` is the local workspace where the command is launched.
|
|
* - `steps` defines which prompt text is matched and which reply is sent.
|
|
* - `timeoutMs` controls when the command is aborted if it stalls.
|
|
* Executes from: not page-bound; runs from a local test workspace on the Node.js side.
|
|
*/
|
|
export async function runInteractiveCommand(
|
|
command: string,
|
|
cwd: string,
|
|
steps: InteractiveStep[],
|
|
timeoutMs: number = 120_000,
|
|
) {
|
|
await new Promise<void>((resolve, reject) => {
|
|
const child = pty.spawn("sh", ["-lc", command], {
|
|
cwd,
|
|
env: {
|
|
...process.env,
|
|
TERM: "xterm-256color",
|
|
},
|
|
cols: 120,
|
|
rows: 30,
|
|
});
|
|
|
|
let currentStep = 0;
|
|
let output = "";
|
|
const timer = setTimeout(() => {
|
|
child.kill();
|
|
reject(new Error(`Interactive command timed out.\n\nCommand: ${command}\n\nOutput:\n${normalizeOutput(output)}`));
|
|
}, timeoutMs);
|
|
|
|
const handleChunk = (chunk: string) => {
|
|
output += chunk;
|
|
const normalizedOutput = normalizeOutput(output);
|
|
|
|
while (currentStep < steps.length && steps[currentStep].match.test(normalizedOutput)) {
|
|
child.write(steps[currentStep].reply);
|
|
currentStep += 1;
|
|
}
|
|
};
|
|
|
|
child.onData(handleChunk);
|
|
child.onExit(({exitCode}) => {
|
|
clearTimeout(timer);
|
|
if (exitCode === 0) {
|
|
resolve();
|
|
return;
|
|
}
|
|
|
|
reject(new Error(`Interactive command failed with exit code ${exitCode}.\n\nCommand: ${command}\n\nOutput:\n${normalizeOutput(output)}`));
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Create and configure a Portabase agent with two Docker-backed databases.
|
|
* Entry point:
|
|
* - `command` is the CLI setup command copied from the agent details page.
|
|
* - `cwd` is the local workspace where the agent is installed.
|
|
* - this helper answers the wizard for PostgreSQL first, then MariaDB.
|
|
* Executes from: not page-bound; runs from a local test workspace on the Node.js side.
|
|
*/
|
|
export async function createAgentWithDockerDatabases(command: string, cwd: string) {
|
|
await runInteractiveCommand(command, cwd, [
|
|
{
|
|
match: /configure.*database|add.*database/i,
|
|
reply: "y\n",
|
|
},
|
|
{
|
|
match: /docker.*new local container|manual.*external|external.*existing/i,
|
|
reply: "\r",
|
|
},
|
|
{
|
|
match: /postgresql|mariadb/i,
|
|
reply: "\r",
|
|
},
|
|
{
|
|
match: /another.*database|add.*another|configure.*another/i,
|
|
reply: "y\n",
|
|
},
|
|
{
|
|
match: /docker.*new local container|manual.*external|external.*existing/i,
|
|
reply: "\r",
|
|
},
|
|
{
|
|
match: /postgresql|mariadb/i,
|
|
reply: "\u001B[B\r",
|
|
},
|
|
{
|
|
match: /another.*database|add.*another|configure.*another/i,
|
|
reply: "n\n",
|
|
},
|
|
]);
|
|
}
|