diff --git a/src/k8s_operations.ts b/src/k8s_operations.ts index 3f9bb6630..b8ae5aa39 100644 --- a/src/k8s_operations.ts +++ b/src/k8s_operations.ts @@ -391,7 +391,7 @@ export async function getSecretValues(name: string, namespace: string): Promise< } return decodedData } catch (error) { - debug(`Failed to get secret values for ${name} in ${namespace}.`) + if (process.env.NODE_ENV !== 'development') debug(`Failed to get secret values for ${name} in ${namespace}.`) } } @@ -417,7 +417,9 @@ export async function getSealedSecretSyncedStatus(name: string, namespace: strin } return 'NotFound' } catch (error) { - debug(`Failed to get SealedSecret synced status for ${name} in ${namespace}.`) + if (process.env.NODE_ENV !== 'development') + debug(`Failed to get SealedSecret synced status for ${name} in ${namespace}.`) + return 'NotFound' } } diff --git a/src/otomi-stack.ts b/src/otomi-stack.ts index 188ae8cf2..27b4c77e0 100644 --- a/src/otomi-stack.ts +++ b/src/otomi-stack.ts @@ -3,15 +3,15 @@ import * as k8s from '@kubernetes/client-node' import { V1ObjectReference } from '@kubernetes/client-node' import Debug from 'debug' -import { ObjectStorageKeyRegions, getRegions } from '@linode/api-v4' +import { getRegions, ObjectStorageKeyRegions } from '@linode/api-v4' import { emptyDir, existsSync, pathExists, rmSync, unlink } from 'fs-extra' -import { readFile, readdir, writeFile } from 'fs/promises' +import { readdir, readFile, writeFile } from 'fs/promises' import { generate as generatePassword } from 'generate-password' import { cloneDeep, filter, get, isArray, isEmpty, map, omit, pick, set, unset } from 'lodash' import { getAppList, getAppSchema, getSpec } from 'src/app' import Db from 'src/db' -import { AlreadyExists, GitPullError, HttpError, OtomiError, PublicUrlExists, ValidationError } from 'src/error' -import { DbMessage, cleanAllSessions, cleanSession, getIo, getSessionStack } from 'src/middleware' +import { AlreadyExists, HttpError, OtomiError, PublicUrlExists, ValidationError } from 'src/error' +import { cleanAllSessions, cleanSession, DbMessage, getIo, getSessionStack } from 'src/middleware' import { App, Backup, @@ -42,6 +42,7 @@ import { import getRepo, { Repo } from 'src/repo' import { arrayToObject, getServiceUrl, getValuesSchema, objectToArray, removeBlankAttributes } from 'src/utils' import { + cleanEnv, CUSTOM_ROOT_CA, DEFAULT_PLATFORM_ADMIN_EMAIL, EDITOR_INACTIVITY_TIMEOUT, @@ -56,7 +57,6 @@ import { PREINSTALLED_EXCLUDED_APPS, TOOLS_HOST, VERSIONS, - cleanEnv, } from 'src/validators' import { v4 as uuidv4 } from 'uuid' import { parse as parseYaml, stringify as stringifyYaml } from 'yaml' @@ -83,7 +83,7 @@ import { getPolicies } from './utils/policiesUtils' import { EncryptedDataRecord, encryptSecretItem, sealedSecretManifest } from './utils/sealedSecretUtils' import { getKeycloakUsers, isValidUsername } from './utils/userUtils' import { ObjectStorageClient } from './utils/wizardUtils' -import { NewChartPayload, fetchWorkloadCatalog, sparseCloneChart } from './utils/workloadUtils' +import { fetchWorkloadCatalog, NewChartPayload, sparseCloneChart } from './utils/workloadUtils' interface ExcludedApp extends App { managed: boolean @@ -1437,16 +1437,15 @@ export default class OtomiStack { }) } debug(`Updated root stack values with ${this.sessionId} changes`) - // and remove editor from the session - await cleanSession(this.sessionId!) const sha = await rootStack.repo.getCommitSha() this.emitPipelineStatus(sha) } catch (e) { - // git conflict with upstream changes, clean up and restore the DB - if (e instanceof GitPullError) await this.doRestore() const msg: DbMessage = { editor: 'system', state: 'corrupt', reason: 'deploy' } getIo().emit('db', msg) throw e + } finally { + // Clean up the session + await cleanSession(this.sessionId!) } } diff --git a/src/repo.ts b/src/repo.ts index 6f8070989..e46ca0b3a 100644 --- a/src/repo.ts +++ b/src/repo.ts @@ -8,7 +8,16 @@ import stringifyJson from 'json-stable-stringify' import { cloneDeep, get, isEmpty, merge, set, unset } from 'lodash' import { basename, dirname, join } from 'path' import simpleGit, { CheckRepoActions, CleanOptions, CommitResult, ResetMode, SimpleGit } from 'simple-git' -import { GIT_BRANCH, GIT_LOCAL_PATH, GIT_PASSWORD, GIT_REPO_URL, GIT_USER, TOOLS_HOST, cleanEnv } from 'src/validators' +import { + cleanEnv, + GIT_BRANCH, + GIT_LOCAL_PATH, + GIT_PASSWORD, + GIT_PUSH_RETRIES, + GIT_REPO_URL, + GIT_USER, + TOOLS_HOST, +} from 'src/validators' import { parse as parseYaml, stringify as stringifyYaml } from 'yaml' import { BASEURL } from './constants' import { GitPullError, HttpError, ValidationError } from './error' @@ -24,6 +33,7 @@ const env = cleanEnv({ GIT_PASSWORD, GIT_REPO_URL, GIT_USER, + GIT_PUSH_RETRIES, TOOLS_HOST, }) @@ -372,16 +382,16 @@ export class Repo { // with the remote root, which might have been modified by another developer // since this is a child branch, we don't need to re-init // retry up to 3 times to pull and push if there are conflicts - const skipInit = true - const retries = 3 + const retries = env.GIT_PUSH_RETRIES for (let attempt = 1; attempt <= retries; attempt++) { + await this.git.pull(this.remote, this.branch, { '--rebase': 'true', '--depth': '5' }) try { - await this.pull(skipInit) await this.push() break } catch (error) { if (attempt === retries) throw error debug(`Attempt ${attempt} failed. Retrying...`) + await new Promise((resolve) => setTimeout(resolve, 50)) } } } catch (e) { diff --git a/src/validators.ts b/src/validators.ts index 7012fa788..ae7b58c85 100644 --- a/src/validators.ts +++ b/src/validators.ts @@ -1,4 +1,4 @@ -import { CleanOptions, CleanedEnvAccessors, ValidatorSpec, bool, cleanEnv as clean, json, num, str } from 'envalid' +import { bool, CleanedEnvAccessors, cleanEnv as clean, CleanOptions, json, num, str, ValidatorSpec } from 'envalid' export const AUTHZ_MOCK_IS_PLATFORM_ADMIN = bool({ desc: 'Indicate if a mocked user is a platform admin', @@ -75,6 +75,10 @@ export const EXPRESS_PAYLOAD_LIMIT = str({ desc: 'The express payload limit', default: '500kb', }) +export const GIT_PUSH_RETRIES = num({ + desc: 'Amount of retries we do to push and pull in the git save function', + default: 10, +}) const { env } = process export function cleanEnv( validators: { [K in keyof T]: ValidatorSpec },