Skip to content

Commit

Permalink
feat: upgrade Node.js, group React UI tabs, add postgres (#381)
Browse files Browse the repository at this point in the history
* upgrade Node.js to 22.9.0
prepare for PostgreSQL

* add tortoise length recommendation

* feat: group tabs in React UI

* feat: add liquibase

* feat: add postgres, terraform to conda

* chore: add terraform gitignore

* delay terraform rollout

* update date on LICENSE

* add extension_audio_separator

* create database bootstrap

* fix mms search bug, description

* add MSVC check to bootstrap

* add db version counter
  • Loading branch information
rsxdalv authored Oct 2, 2024
1 parent 1e3e75a commit 0ce1550
Show file tree
Hide file tree
Showing 52 changed files with 1,053 additions and 383 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,6 @@ node_modules/
# Temporary files used by some modules
output.wav
log.out

# Database
/data/postgres/
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ FROM nvidia/cuda:11.8.0-devel-ubuntu22.04 AS env_base
RUN apt-get update && apt-get install --no-install-recommends -y \
git vim nano build-essential python3-dev python3-venv python3-pip gcc g++ ffmpeg

ENV NODE_VERSION=20.17.0
ENV NODE_VERSION=22.9.0
RUN apt-get update && apt install -y curl
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
ENV NVM_DIR=/root/.nvm
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Roberts Slisans
Copyright (c) 2024 Roberts Slisans

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
15 changes: 15 additions & 0 deletions extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,21 @@
"website": "https://github.com/rsxdalv/extension_parler_tts",
"extension_website": "https://github.com/rsxdalv/extension_parler_tts",
"extension_platform_version": "0.0.1"
},
{
"package_name": "extension_audio_separator",
"name": "Audio Separator",
"version": "0.0.1",
"requirements": "git+https://github.com/rsxdalv/extension_audio_separator@main",
"description": "Audio Separator allows separating audio files into multiple audio files.",
"extension_type": "interface",
"extension_class": "audio-conversion",
"author": "rsxdalv",
"extension_author": "rsxdalv",
"license": "MIT",
"website": "https://github.com/rsxdalv/extension_audio_separator",
"extension_website": "https://github.com/rsxdalv/extension_audio_separator",
"extension_platform_version": "0.0.1"
}
],
"decorators": [
Expand Down
1 change: 1 addition & 0 deletions installer_scripts/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ output.log
.major_version
.python_version
.pip_packages
.db_version

# Diagnostic
diagnostic.txt
2 changes: 1 addition & 1 deletion installer_scripts/init_mamba.bat
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ set USERPROFILE=%cd%\installer_files\profile
@rem figure out whether git and conda needs to be installed
if exist "%INSTALL_ENV_DIR%" set PATH=%INSTALL_ENV_DIR%;%INSTALL_ENV_DIR%\Library\bin;%INSTALL_ENV_DIR%\Scripts;%INSTALL_ENV_DIR%\Library\usr\bin;%PATH%

set PACKAGES_TO_INSTALL=git python=3.10.11 nodejs=20.17.0 conda pip==23.3.2
set PACKAGES_TO_INSTALL=git python=3.10.11 nodejs=22.9.0 conda pip==23.3.2 conda-forge::vswhere

@REM if not exist "%MAMBA_ROOT_PREFIX%\micromamba.exe" set umamba_exists=F
if not exist "temp" mkdir temp
Expand Down
2 changes: 1 addition & 1 deletion installer_scripts/init_mamba.sh
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ umamba_exists="F"
# figure out whether git and conda needs to be installed
if [ -e "$INSTALL_ENV_DIR" ]; then export PATH="$INSTALL_ENV_DIR/bin:$PATH"; fi

PACKAGES_TO_INSTALL="python=3.10.11 nodejs=20.17.0 conda pip==23.3.2"
PACKAGES_TO_INSTALL="python=3.10.11 nodejs=22.9.0 conda pip==23.3.2"

if ! hash "git" &>/dev/null; then PACKAGES_TO_INSTALL="$PACKAGES_TO_INSTALL git"; fi

Expand Down
119 changes: 119 additions & 0 deletions installer_scripts/js/applyDatabaseConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
const fs = require("fs");
const { resolve } = require("path");
const { displayMessage } = require("./displayMessage.js");
const { $sh } = require("./shell.js");

async function applyDatabaseConfig() {
const db_conf = {
// location: "data/postgres",
location: resolve(__dirname, "..", "..", "data", "postgres"),
port: 5432,
database: "webui",
username: "postgres",
password: "",
ssl: false,
};

const initializeDatabase = async () => {
if (fs.existsSync(db_conf.location)) {
displayMessage("Database already initialized, skipping...");
return;
}
displayMessage("Initializing database...");
await $sh(`initdb -D ${db_conf.location} -U ${db_conf.username}`);
displayMessage("Successfully initialized database");
};

await initializeDatabase();

const withDatabase = async (func) => {
const startDatabase = async () => {
displayMessage("Starting database...");
await $sh(`pg_ctl start -D ${db_conf.location}`);
displayMessage("Successfully started database");
};

const stopDatabase = async () => {
displayMessage("Stopping database...");
await $sh(`pg_ctl stop -D ${db_conf.location} -m fast`);
displayMessage("Successfully stopped database");
};

const awaitDatabase = async (counter = 0) => {
try {
await $sh(`pg_isready -U ${db_conf.username}`);
} catch (error) {
displayMessage(`Database is not ready, retrying... ${counter}/10`);
if (counter < 10) {
await awaitDatabase(counter + 1);
} else {
displayMessage("Database is not ready, aborting...");
throw error;
}
}
};
await startDatabase();
await awaitDatabase();
try {
await func();
} finally {
await stopDatabase();
}
};

const db_version = "1";
const db_version_file = resolve(__dirname, "..", ".db_version");

const withDatabaseVersioning = async (func) => {
if (fs.existsSync(db_version_file)) {
const version = fs.readFileSync(db_version_file, "utf8");
if (version === db_version) {
displayMessage(
`Database is already up to date version=${version}, skipping...`
);
return;
} else {
displayMessage(
`Database is not up to date, current version=${version}, version=${db_version}, upgrading...`
);
await func();
fs.writeFileSync(db_version_file, db_version);
}
}
};

await withDatabaseVersioning(() =>
withDatabase(async () => {
const createDB = async () => {
displayMessage(`Creating database ${db_conf.database}`);
// create a database, error if it already exists
try {
await $sh(`createdb -U ${db_conf.username} ${db_conf.database}`);
} catch (error) {
displayMessage("Database already exists, skipping...");
return;
}
displayMessage("Successfully created database");
};
const applyMigrations = async () => {
const sql = async (strings) => {
// Since we're assuming no interpolated values, we can directly use the string
const query = strings[0];
const psqlCommand = `psql -U ${db_conf.username} -d ${
db_conf.database
} -c "${query.replace(/"/g, '\\"').replace(/\n/g, " ")}"`;
$sh(psqlCommand);
};

await sql`CREATE TABLE IF NOT EXISTS generations (
id SERIAL PRIMARY KEY,
metadata JSONB
);`;
};
await createDB();
await applyMigrations();
})
);
}

exports.applyDatabaseConfig = applyDatabaseConfig;
65 changes: 45 additions & 20 deletions installer_scripts/js/initializeApp.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
const fs = require("fs");
const { resolve } = require("path");
const { displayError, displayMessage } = require("./displayMessage.js");
const { processExit } = require("./processExit.js");
const { menu } = require("./menu.js");
const { $, $$, $sh } = require("./shell.js");
const { applyDatabaseConfig } = require("./applyDatabaseConfig.js");

const DEBUG_DRY_RUN = false;

// const torchVersion = $$(`pip show torch | grep Version`);
const torchVersion = "2.3.1";
const cudaVersion = "11.8";

Expand All @@ -15,8 +16,11 @@ const cudaVersion = "11.8";
const pythonVersion = `3.10.11`;
const pythonPackage = `python=${pythonVersion}`;
const ffmpegPackage = `conda-forge::ffmpeg=4.4.2[build=lgpl*]`;
const nodePackage = ``;
// const nodePackage = `node=20.17.0`;
const nodePackage = `conda-forge::nodejs=22.9.0`;
const anacondaPostgresqlPackage = `conda-forge::postgresql=16.4`;
// const terraformPackage = `conda-forge::terraform=1.8.2`;
const terraformPackage = ``;

const cudaChannels = [
"",
"pytorch",
Expand All @@ -25,14 +29,32 @@ const cudaChannels = [
].join(" -c ");
const cpuChannels = ["", "pytorch"].join(" -c ");

const cudaPackages = `pytorch[version=${torchVersion},build=py3.10_cuda${cudaVersion}*] torchvision torchaudio pytorch-cuda=${cudaVersion} cuda-toolkit ninja`;
const cudaPytorchInstall$ = `conda install -y -k ${nodePackage} ${ffmpegPackage} ${cudaPackages} ${cudaChannels}`;
const windowsOnlyPackages =
process.platform === "win32" ? ["conda-forge::vswhere"] : [];

const cpuPackages = `pytorch=${torchVersion} torchvision torchaudio cpuonly`;
const pytorchCPUInstall$ = `conda install -y -k ${nodePackage} ${ffmpegPackage} ${cpuPackages} ${cpuChannels}`;
const cudaPackages = `pytorch[version=${torchVersion},build=py3.10_cuda${cudaVersion}*] pytorch-cuda=${cudaVersion} torchvision torchaudio cuda-toolkit ninja`;
const cudaPytorchInstall$ = [
"conda install -y -k",
...windowsOnlyPackages,
terraformPackage,
anacondaPostgresqlPackage,
nodePackage,
ffmpegPackage,
cudaPackages,
cudaChannels,
].join(" ");

// console.log(cudaPytorchInstall$);
// console.log(pytorchCPUInstall$);
const cpuPackages = `pytorch=${torchVersion} torchvision torchaudio cpuonly`;
const pytorchCPUInstall$ = [
"conda install -y -k",
...windowsOnlyPackages,
terraformPackage,
anacondaPostgresqlPackage,
nodePackage,
ffmpegPackage,
cpuPackages,
cpuChannels,
].join(" ");

const ensurePythonVersion = async () => {
try {
Expand Down Expand Up @@ -99,13 +121,15 @@ Select the device (GPU/CPU) you are using to run the application:
`
);

const gpuFile = "./installer_scripts/.gpu";
const majorVersionFile = "./installer_scripts/.major_version";
const pipPackagesFile = "./installer_scripts/.pip_packages";
const majorVersion = "2"; // to be bumped
const getInstallerFilesPath = (file) => resolve(__dirname, "..", file);

const gpuFile = getInstallerFilesPath(".gpu");
const majorVersionFile = getInstallerFilesPath(".major_version");
const pipPackagesFile = getInstallerFilesPath(".pip_packages");
const majorVersion = "3";

const versions = JSON.parse(
fs.readFileSync("./installer_scripts/versions.json")
fs.readFileSync(getInstallerFilesPath("versions.json"))
);
const newPipPackagesVersion = String(versions.pip_packages);

Expand All @@ -116,9 +140,7 @@ const readGeneric = (file) => {
return -1;
};

const saveGeneric = (file, data) => {
fs.writeFileSync(file, data.toString());
};
const saveGeneric = (file, data) => fs.writeFileSync(file, data.toString());

const readMajorVersion = () => readGeneric(majorVersionFile);
const saveMajorVersion = (data) => saveGeneric(majorVersionFile, data);
Expand All @@ -128,9 +150,7 @@ const readGPUChoice = () => readGeneric(gpuFile);
const saveGPUChoice = (data) => saveGeneric(gpuFile, data);

const removeGPUChoice = () => {
if (fs.existsSync(gpuFile)) {
fs.unlinkSync(gpuFile);
}
if (fs.existsSync(gpuFile)) fs.unlinkSync(gpuFile);
};

const dry_run_flag = DEBUG_DRY_RUN ? "--dry-run " : "";
Expand Down Expand Up @@ -202,6 +222,11 @@ const FORCE_REINSTALL = process.env.FORCE_REINSTALL ? true : false;
const initializeApp = async () => {
displayMessage("Ensuring that python has the correct version...");
await ensurePythonVersion();
try {
await applyDatabaseConfig();
} catch (error) {
displayError("Failed to apply database config");
}
displayMessage("Checking if Torch is installed...");
if (readMajorVersion() === majorVersion && !FORCE_REINSTALL) {
if (await checkIfTorchInstalled()) {
Expand Down
29 changes: 29 additions & 0 deletions installer_scripts/root.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,35 @@ if ($LASTEXITCODE -ne 0) {
exit 1
}

$env:Path += ";$PSScriptRoot\..\installer_files\env\Library\bin\"

if (!(Get-Command "vswhere" -ErrorAction SilentlyContinue)) {
Write-Host "Critical Warning: vswhere is not installed, automatic validation of Visual Studio Build Tools installation will not work."
Write-Host "For more information, please visit:"
Write-Host "https://github.com/microsoft/vswhere"
Write-Host "The app will try to launch but might fail."
} else {
Write-Host "vswhere is installed, checking for Visual Studio Build Tools installation..."
$vswhereOutput = vswhere -products * -format json | ConvertFrom-Json
if ($vswhereOutput.length -eq 0) {
Write-Host "Warning: Visual Studio compiler is not installed."
if (!(Get-Command "winget" -ErrorAction SilentlyContinue)) {
Write-Host "Warning: winget is not installed, automatic installation of Visual Studio Build Tools will not work."
Write-Host "Please install Visual Studio Build Tools manually and restart the installer."
Write-Host "(Note: The full Visual Studio is NOT required, only the Build Tools)"
Write-Host "For more information, please visit:"
Write-Host "https://learn.microsoft.com/en-us/cpp/build/vscpp-step-0-installation?view=msvc-170"
exit 1
} else {
Write-Host "Attempting to install Visual Studio Build Tools using winget..."
Write-Host "This will open a new window, please follow the instructions."
winget install Microsoft.VisualStudio.2022.BuildTools --accept-package-agreements --accept-source-agreements
}
} else {
Write-Host "Visual Studio Build Tools is installed, continuing..."
}
}

& "$PSScriptRoot\init_app.bat"
if ($LASTEXITCODE -ne 0) {
Write-Host "Failed to init the app, exiting..."
Expand Down
39 changes: 39 additions & 0 deletions installer_scripts/terraform/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log
crash.*.log

# Exclude all .tfvars files, which are likely to contain sensitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
*.tfvars
*.tfvars.json

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Ignore transient lock info files created by terraform apply
.terraform.tfstate.lock.info

# Include override files you do wish to add to version control using negated pattern
# !example_override.tf

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*

# Ignore CLI configuration files
.terraformrc
terraform.rc

.terraform.lock.hcl
Loading

0 comments on commit 0ce1550

Please sign in to comment.