fix(cli): load .env file on each access to getEnv to ensure updated values

This commit is contained in:
Nicolas Meienberger 2023-08-22 22:31:10 +02:00 committed by Nicolas Meienberger
parent 24c4d0f8af
commit 26bb80e743
6 changed files with 55 additions and 28 deletions

View file

@ -7,19 +7,9 @@ import { copyDataDir, generateEnvFile } from './app.helpers';
import { fileLogger } from '@/utils/logger/file-logger';
export class AppExecutors {
private readonly rootFolderHost: string;
private readonly storagePath: string;
private readonly appsRepoId: string;
private readonly logger;
constructor() {
const { rootFolderHost, storagePath, appsRepoId } = getEnv();
this.rootFolderHost = rootFolderHost;
this.storagePath = storagePath;
this.appsRepoId = appsRepoId;
this.logger = fileLogger;
}
@ -33,10 +23,12 @@ export class AppExecutors {
};
private getAppPaths = (appId: string) => {
const appDataDirPath = path.join(this.storagePath, 'app-data', appId);
const appDirPath = path.join(this.rootFolderHost, 'apps', appId);
const { rootFolderHost, storagePath, appsRepoId } = getEnv();
const appDataDirPath = path.join(storagePath, 'app-data', appId);
const appDirPath = path.join(rootFolderHost, 'apps', appId);
const configJsonPath = path.join(appDirPath, 'config.json');
const repoPath = path.join(this.rootFolderHost, 'repos', this.appsRepoId, 'apps', appId);
const repoPath = path.join(rootFolderHost, 'repos', appsRepoId, 'apps', appId);
return { appDataDirPath, appDirPath, configJsonPath, repoPath };
};
@ -69,8 +61,10 @@ export class AppExecutors {
* @param {string} appId - App id
*/
private ensureAppDir = async (appId: string) => {
const { rootFolderHost } = getEnv();
const { appDirPath, repoPath } = this.getAppPaths(appId);
const dockerFilePath = path.join(this.rootFolderHost, 'apps', appId, 'docker-compose.yml');
const dockerFilePath = path.join(rootFolderHost, 'apps', appId, 'docker-compose.yml');
if (!(await pathExists(dockerFilePath))) {
// delete eventual app folder if exists
@ -90,15 +84,17 @@ export class AppExecutors {
*/
public installApp = async (appId: string, config: Record<string, unknown>) => {
try {
const { rootFolderHost, appsRepoId } = getEnv();
const { appDirPath, repoPath, appDataDirPath } = this.getAppPaths(appId);
this.logger.info(`Installing app ${appId}`);
// Check if app exists in repo
const apps = await fs.promises.readdir(path.join(this.rootFolderHost, 'repos', this.appsRepoId, 'apps'));
const apps = await fs.promises.readdir(path.join(rootFolderHost, 'repos', appsRepoId, 'apps'));
if (!apps.includes(appId)) {
this.logger.error(`App ${appId} not found in repo ${this.appsRepoId}`);
return { success: false, message: `App ${appId} not found in repo ${this.appsRepoId}` };
this.logger.error(`App ${appId} not found in repo ${appsRepoId}`);
return { success: false, message: `App ${appId} not found in repo ${appsRepoId}` };
}
// Delete app folder if exists

View file

@ -9,13 +9,9 @@ import { fileLogger } from '@/utils/logger/file-logger';
const execAsync = promisify(exec);
export class RepoExecutors {
private readonly rootFolderHost: string;
private readonly logger;
constructor() {
const { rootFolderHost } = getEnv();
this.rootFolderHost = rootFolderHost;
this.logger = fileLogger;
}
@ -39,8 +35,10 @@ export class RepoExecutors {
*/
public cloneRepo = async (repoUrl: string) => {
try {
const { rootFolderHost } = getEnv();
const repoHash = getRepoHash(repoUrl);
const repoPath = path.join(this.rootFolderHost, 'repos', repoHash);
const repoPath = path.join(rootFolderHost, 'repos', repoHash);
if (await pathExists(repoPath)) {
this.logger.info(`Repo ${repoUrl} already exists`);
@ -65,8 +63,10 @@ export class RepoExecutors {
*/
public pullRepo = async (repoUrl: string) => {
try {
const { rootFolderHost } = getEnv();
const repoHash = getRepoHash(repoUrl);
const repoPath = path.join(this.rootFolderHost, 'repos', repoHash);
const repoPath = path.join(rootFolderHost, 'repos', repoHash);
if (!(await pathExists(repoPath))) {
this.logger.info(`Repo ${repoUrl} does not exist`);

View file

@ -8,6 +8,7 @@ import { exec, spawn } from 'child_process';
import si from 'systeminformation';
import { Stream } from 'stream';
import { promisify } from 'util';
import dotenv from 'dotenv';
import { AppExecutors } from '../app/app.executors';
import { copySystemFiles, generateSystemEnvFile, generateTlsCertificates } from './system.helpers';
import { TerminalSpinner } from '@/utils/logger/terminal-spinner';
@ -60,6 +61,7 @@ export class SystemExecutors {
path.join(rootFolderHost, 'state'),
path.join(rootFolderHost, '.env'),
path.join(rootFolderHost, 'docker-compose.yml'),
path.join(rootFolderHost, 'VERSION'),
];
// Give permission to read and write to all files and folders for the current user
@ -138,13 +140,19 @@ export class SystemExecutors {
spinner.start();
spinner.setMessage('Copying system files...');
await copySystemFiles();
spinner.done('System files copied');
await this.ensureFilePermissions(this.rootFolder);
spinner.setMessage('Generating system env file...');
spinner.start();
const envMap = await generateSystemEnvFile();
spinner.done('System env file generated');
// Reload env variables after generating the env file
dotenv.config({ path: this.envFile, override: true });
// Stop and Remove container tipi if exists
spinner.setMessage('Stopping and removing containers...');
spinner.start();

View file

@ -179,6 +179,29 @@ export const generateSystemEnvFile = async () => {
return envMap;
};
/**
* Sets the value of an environment variable in the .env file
*
* @param {string} key - The key of the environment variable
* @param {string} value - The value of the environment variable
*/
export const setEnvVariable = async (key: EnvKeys, value: string) => {
const rootFolder = process.cwd();
const envFilePath = path.join(rootFolder, '.env');
if (!(await pathExists(envFilePath))) {
await fs.promises.writeFile(envFilePath, '');
}
const envFile = await fs.promises.readFile(envFilePath, 'utf-8');
const envMap: Map<EnvKeys, string> = envStringToMap(envFile);
envMap.set(key, value);
await fs.promises.writeFile(envFilePath, envMapToString(envMap));
};
/**
* Copies the system files from the assets folder to the current working directory
*/

View file

@ -2,9 +2,9 @@ import { z } from 'zod';
import dotenv from 'dotenv';
if (process.env.NODE_ENV === 'development') {
dotenv.config({ path: '.env.dev' });
dotenv.config({ path: '.env.dev', override: true });
} else {
dotenv.config();
dotenv.config({ override: true });
}
const environmentSchema = z

View file

@ -177,12 +177,12 @@ if [[ "${UPDATE}" == "false" ]]; then
fi
curl --location "$URL" -o ./runtipi-cli
sudo chmod +x ./runtipi-cli
chmod +x ./runtipi-cli
# Check if user is in docker group
if ! groups | grep -q docker; then
echo "User is not in docker group. Please make sure your user is in the docker group and restart the script."
echo "You can add your user to the docker group by running: 'sudo usermod -aG docker $USER' and then exit the shell and restart the script."
echo "User is not in docker group. Please make sure your user is allowed to run docker commands and restart the script."
echo "See https://docs.docker.com/engine/install/linux-postinstall/ for more information."
exit 1
fi