From 55294eb59bb8f9331279b6e97310d2f549258cb4 Mon Sep 17 00:00:00 2001 From: shu-unifra Date: Wed, 23 Apr 2025 17:23:29 +0900 Subject: [PATCH 1/7] 1. fix bug that if reexecute 'setup gen-keystore', the l2-sequencer-production-*.yaml did not get the latest data like "L2GETH_SIGNER_ADDRESS" 2. fix bug that 'setup push-secrets' did not update prefix of remoteRef.key in file 'l2-sequencer-production-*.yaml' 3. remind users that passowrd of keystore can not be empty. --- src/commands/setup/gen-keystore.ts | 9 ++++++++- src/commands/setup/prep-charts.ts | 20 +++++++++++++------- src/commands/setup/push-secrets.ts | 14 +++++++++----- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/commands/setup/gen-keystore.ts b/src/commands/setup/gen-keystore.ts index 76137f9..ea57637 100644 --- a/src/commands/setup/gen-keystore.ts +++ b/src/commands/setup/gen-keystore.ts @@ -52,7 +52,14 @@ export default class SetupGenKeystore extends Command { } private async generateSequencerKeystore(index: number): Promise { - const password = await input({ message: `Enter a password for sequencer-${index} keystore:` }) + let password = '' + while (!password) { + password = await input({ message: `Enter a password for sequencer-${index} keystore:` }) + if (!password) { + console.log('Password cannot be empty. Please try again.') + } + } + const wallet = Wallet.createRandom() const encryptedJson = await wallet.encrypt(password) return { diff --git a/src/commands/setup/prep-charts.ts b/src/commands/setup/prep-charts.ts index e7def21..b4052ab 100644 --- a/src/commands/setup/prep-charts.ts +++ b/src/commands/setup/prep-charts.ts @@ -138,9 +138,9 @@ export default class SetupPrepCharts extends Command { if (configMapData && typeof configMapData === 'object' && 'data' in configMapData) { const envData = (configMapData as any).data for (const [key, value] of Object.entries(envData)) { - if (value === '' || value === '[""]' || value === '[]' || - (Array.isArray(value) && (value.length === 0 || (value.length === 1 && value[0] === ''))) || - value === null || value === undefined) { + // if (value === '' || value === '[""]' || value === '[]' || + // (Array.isArray(value) && (value.length === 0 || (value.length === 1 && value[0] === ''))) || + // value === null || value === undefined) { const configMapping = this.configMapping[key] if (configMapping) { let configKey: string @@ -157,14 +157,20 @@ export default class SetupPrepCharts extends Command { } else { newValue = String(configValue) } - changes.push({ key, oldValue: JSON.stringify(value), newValue: newValue }) - envData[key] = newValue - updated = true + + if(chartName === "l1-devnet" && key === "CHAIN_ID"){ + continue; + } + if (newValue != value) { + changes.push({ key, oldValue: JSON.stringify(value), newValue: newValue }) + envData[key] = newValue + updated = true + } } else { this.log(chalk.yellow(`${chartName}: No value found for ${configKey}`)) } } - } + //} } } } diff --git a/src/commands/setup/push-secrets.ts b/src/commands/setup/push-secrets.ts index 9924daf..36f51e8 100644 --- a/src/commands/setup/push-secrets.ts +++ b/src/commands/setup/push-secrets.ts @@ -369,7 +369,7 @@ export default class SetupPushSecrets extends Command { } } - private async updateProductionYaml(provider: string): Promise { + private async updateProductionYaml(provider: string, prefixName?: string): Promise { const valuesDir = path.join(process.cwd(), this.flags['values-dir']); if (!fs.existsSync(valuesDir)) { this.error(chalk.red(`Values directory not found at ${valuesDir}`)); @@ -432,17 +432,19 @@ export default class SetupPushSecrets extends Command { } // Update remoteRef for l2-sequencer secrets - if (secretName.match(/^l2-sequencer-\d+-secret$/)) { + if (secretName.match(/^l2-sequencer-secret-\d+-env$/)) { for (const data of secret.data) { if (data.remoteRef && data.remoteRef.key) { - data.remoteRef.key = 'l2-sequencer-secret'; + // Use the prefixName if available + const prefix = prefixName || (data.remoteRef.key.startsWith('scroll/') ? 'scroll' : ''); + data.remoteRef.key = `${prefix}/l2-sequencer-secret-env`; updated = true; } } } } } - + if (updated) { const newContent = yaml.dump(yamlContent, { lineWidth: -1, noRefs: true, quotingType: '"', forceQuotes: true }); fs.writeFileSync(yamlPath, newContent); @@ -470,11 +472,13 @@ export default class SetupPushSecrets extends Command { let service: SecretService let provider: string + let prefixName: string | undefined if (secretService === 'aws') { const awsCredentials = await this.getAWSCredentials() service = new AWSSecretService(awsCredentials.secretRegion, awsCredentials.prefixName, flags.debug) provider = 'aws' + prefixName = awsCredentials.prefixName } else if (secretService === 'vault') { service = new HashicorpVaultDevService(flags.debug) provider = 'vault' @@ -491,7 +495,7 @@ export default class SetupPushSecrets extends Command { }) if (shouldUpdateYaml) { - await this.updateProductionYaml(provider) + await this.updateProductionYaml(provider, prefixName) this.log(chalk.green('Production YAML files updated successfully')) } else { this.log(chalk.yellow('Skipped updating production YAML files')) From a017b71709d3082ba14c61936ab10407e1f0a194 Mon Sep 17 00:00:00 2001 From: shu-unifra Date: Fri, 25 Apr 2025 16:44:09 +0900 Subject: [PATCH 2/7] fix bug of push-secrets --- src/commands/setup/prep-charts.ts | 8 +- src/commands/setup/push-secrets.ts | 149 ++++++++++++++++++++--------- 2 files changed, 107 insertions(+), 50 deletions(-) diff --git a/src/commands/setup/prep-charts.ts b/src/commands/setup/prep-charts.ts index b4052ab..4341e82 100644 --- a/src/commands/setup/prep-charts.ts +++ b/src/commands/setup/prep-charts.ts @@ -149,6 +149,10 @@ export default class SetupPrepCharts extends Command { } else { configKey = configMapping } + if(chartName === "l1-devnet" && key === "CHAIN_ID"){ + configKey = "general.CHAIN_ID_L1"; + } + const configValue = this.getConfigValue(configKey) if (configValue !== undefined && configValue !== null) { let newValue: string | string[] @@ -157,10 +161,6 @@ export default class SetupPrepCharts extends Command { } else { newValue = String(configValue) } - - if(chartName === "l1-devnet" && key === "CHAIN_ID"){ - continue; - } if (newValue != value) { changes.push({ key, oldValue: JSON.stringify(value), newValue: newValue }) envData[key] = newValue diff --git a/src/commands/setup/push-secrets.ts b/src/commands/setup/push-secrets.ts index 36f51e8..8faf973 100644 --- a/src/commands/setup/push-secrets.ts +++ b/src/commands/setup/push-secrets.ts @@ -33,6 +33,10 @@ class AWSSecretService implements SecretService { const fullSecretName = `${this.prefixName}/${secretName}` const jsonContent = JSON.stringify(content) const escapedJsonContent = jsonContent.replace(/'/g, "'\\''") + if (!jsonContent) { + console.log(chalk.red(`Skipping secret: ${secretName} because it is empty`)) + return + } if (await this.secretExists(secretName)) { const shouldOverride = await confirm({ @@ -112,15 +116,31 @@ class AWSSecretService implements SecretService { let l2SequencerSecrets: Record = {} for (const file of envFiles) { - const secretName = path.basename(file, '.env') - if (secretName.startsWith('l2-sequencer-')) { + const baseName = path.basename(file, '.env') + + // Special handling for l2-sequencer-N-secret.env files + if (baseName.match(/^l2-sequencer-\d+-secret$/)) { + const sequencerIndex = baseName.match(/l2-sequencer-(\d+)-secret/)?.[1] || '0' + const secretName = `l2-sequencer-secret-${sequencerIndex}-env` + console.log(chalk.cyan(`Processing L2 Sequencer secret: ${secretName}`)) const data = await this.convertEnvToDict(path.join(secretsDir, file)) - l2SequencerSecrets = { ...l2SequencerSecrets, ...data } + await this.createOrUpdateSecret(data, secretName) + + // Also add to combined secret with index suffix for backward compatibility + for (const [key, value] of Object.entries(data)) { + // If key already has index suffix, use it as is, otherwise add index suffix + if (key.endsWith(`_${sequencerIndex}`)) { + l2SequencerSecrets[key] = value + } else { + l2SequencerSecrets[`${key}_${sequencerIndex}`] = value + } + } } else { - console.log(chalk.cyan(`Processing ENV secret: ${secretName}-env`)) + const secretName = `${baseName}-env` + console.log(chalk.cyan(`Processing ENV secret: ${secretName}`)) const data = await this.convertEnvToDict(path.join(secretsDir, file)) - await this.createOrUpdateSecret(data, `${secretName}-env`) + await this.createOrUpdateSecret(data, secretName) } } @@ -134,9 +154,11 @@ class AWSSecretService implements SecretService { class HashicorpVaultDevService implements SecretService { private debug: boolean + private pathPrefix: string - constructor(debug: boolean) { + constructor(debug: boolean, pathPrefix: string = 'scroll') { this.debug = debug + this.pathPrefix = pathPrefix } private async runCommand(command: string): Promise { @@ -195,7 +217,11 @@ class HashicorpVaultDevService implements SecretService { .map(([key, value]) => `${key}='${value.replace(/'/g, "'\\''")}'`) .join(' ') - const command = `vault kv put scroll/${secretName} ${kvPairs}` + if (!kvPairs) { + console.log(chalk.red(`Skipping secret: ${secretName} because it is empty`)) + return + } + const command = `vault kv put ${this.pathPrefix}/${secretName} ${kvPairs}` if (this.debug) { console.log(chalk.yellow('--- Debug Output ---')) @@ -206,9 +232,9 @@ class HashicorpVaultDevService implements SecretService { try { await this.runCommand(command) - console.log(chalk.green(`Successfully pushed secret: scroll/${secretName}`)) + console.log(chalk.green(`Successfully pushed secret: ${this.pathPrefix}/${secretName}`)) } catch (error) { - console.error(chalk.red(`Failed to push secret: scroll/${secretName}`)) + console.error(chalk.red(`Failed to push secret: ${this.pathPrefix}/${secretName}`)) console.error(chalk.red(`Error: ${error}`)) } } @@ -217,7 +243,7 @@ class HashicorpVaultDevService implements SecretService { try { const jsonContent = JSON.parse(content); const escapedJson = JSON.stringify(jsonContent).replace(/'/g, "'\\''"); - const command = `vault kv put scroll/${secretName} migrate-db.json='${escapedJson}'`; + const command = `vault kv put ${this.pathPrefix}/${secretName} migrate-db.json='${escapedJson}'`; if (this.debug) { console.log(chalk.yellow('--- Debug Output ---')); @@ -226,10 +252,15 @@ class HashicorpVaultDevService implements SecretService { console.log(chalk.yellow('-------------------')); } + if (!jsonContent) { + console.log(chalk.red(`Skipping secret: ${secretName} because it is empty`)) + return + } + await this.runCommand(command); - console.log(chalk.green(`Successfully pushed JSON secret: scroll/${secretName}`)); + console.log(chalk.green(`Successfully pushed JSON secret: ${this.pathPrefix}/${secretName}`)); } catch (error) { - console.error(chalk.red(`Failed to push JSON secret: scroll/${secretName}`)); + console.error(chalk.red(`Failed to push JSON secret: ${this.pathPrefix}/${secretName}`)); console.error(chalk.red(`Error: ${error}`)); } } @@ -245,26 +276,26 @@ class HashicorpVaultDevService implements SecretService { } // Check if the KV secrets engine is already enabled - const isEnabled = await this.isSecretEngineEnabled('scroll') + const isEnabled = await this.isSecretEngineEnabled(this.pathPrefix) if (!isEnabled) { // Enable the KV secrets engine only if it's not already enabled try { - await this.runCommand("vault secrets enable -path=scroll kv-v2") - console.log(chalk.green("KV secrets engine enabled at path 'scroll'")) + await this.runCommand(`vault secrets enable -path=${this.pathPrefix} kv-v2`) + console.log(chalk.green(`KV secrets engine enabled at path '${this.pathPrefix}'`)) } catch (error: unknown) { if (error instanceof Error) { // If the error is about the path already in use, we can ignore it - if (!error.message.includes("path is already in use at scroll/")) { + if (!error.message.includes(`path is already in use at ${this.pathPrefix}/`)) { throw error } - console.log(chalk.yellow("KV secrets engine already enabled at path 'scroll'")) + console.log(chalk.yellow(`KV secrets engine already enabled at path '${this.pathPrefix}'`)) } else { // If it's not an Error instance, rethrow it throw error } } } else { - console.log(chalk.yellow("KV secrets engine already enabled at path 'scroll'")) + console.log(chalk.yellow(`KV secrets engine already enabled at path '${this.pathPrefix}'`)) } const secretsDir = path.join(process.cwd(), 'secrets') @@ -273,7 +304,7 @@ class HashicorpVaultDevService implements SecretService { const jsonFiles = fs.readdirSync(secretsDir).filter(file => file.endsWith('.json')) for (const file of jsonFiles) { const secretName = path.basename(file, '.json') - console.log(chalk.cyan(`Processing JSON secret: scroll/${secretName}`)) + console.log(chalk.cyan(`Processing JSON secret: ${this.pathPrefix}/${secretName}`)) const content = await fs.promises.readFile(path.join(secretsDir, file), 'utf-8') await this.pushJsonToVault(secretName, content) } @@ -283,21 +314,37 @@ class HashicorpVaultDevService implements SecretService { let l2SequencerSecrets: Record = {} for (const file of envFiles) { - const secretName = path.basename(file, '.env') + '-env' - if (secretName.startsWith('l2-sequencer-')) { - console.log(chalk.cyan(`Processing L2 Sequencer secret: ${secretName}`)) + const baseName = path.basename(file, '.env') + + // Special handling for l2-sequencer-N-secret.env files + if (baseName.match(/^l2-sequencer-\d+-secret$/)) { + const sequencerIndex = baseName.match(/l2-sequencer-(\d+)-secret/)?.[1] || '0' + const secretName = `l2-sequencer-secret-${sequencerIndex}-env` + + console.log(chalk.cyan(`Processing L2 Sequencer secret: ${this.pathPrefix}/${secretName}`)) const data = await this.convertEnvToDict(path.join(secretsDir, file)) - l2SequencerSecrets = { ...l2SequencerSecrets, ...data } + await this.pushToVault(secretName, data) + + // Also add to combined secret with index suffix for backward compatibility + for (const [key, value] of Object.entries(data)) { + // If key already has index suffix, use it as is, otherwise add index suffix + if (key.endsWith(`_${sequencerIndex}`)) { + l2SequencerSecrets[key] = value + } else { + l2SequencerSecrets[`${key}_${sequencerIndex}`] = value + } + } } else { - console.log(chalk.cyan(`Processing ENV secret: scroll/${secretName}`)) + const secretName = `${baseName}-env` + console.log(chalk.cyan(`Processing ENV secret: ${this.pathPrefix}/${secretName}`)) const data = await this.convertEnvToDict(path.join(secretsDir, file)) await this.pushToVault(secretName, data) } } - // Push combined L2 Sequencer secrets + // Push combined L2 Sequencer secrets for backward compatibility if (Object.keys(l2SequencerSecrets).length > 0) { - console.log(chalk.cyan(`Processing combined L2 Sequencer secrets: scroll/l2-sequencer-secret-env`)) + console.log(chalk.cyan(`Processing combined L2 Sequencer secrets: ${this.pathPrefix}/l2-sequencer-secret-env`)) await this.pushToVault('l2-sequencer-secret-env', l2SequencerSecrets) } @@ -369,17 +416,16 @@ export default class SetupPushSecrets extends Command { } } - private async updateProductionYaml(provider: string, prefixName?: string): Promise { + private async updateProductionYaml(provider: string, credentials: Record): Promise { const valuesDir = path.join(process.cwd(), this.flags['values-dir']); if (!fs.existsSync(valuesDir)) { this.error(chalk.red(`Values directory not found at ${valuesDir}`)); } - - let credentials: Record; + let prefixName: string | undefined; if (provider === 'vault') { - credentials = await this.getVaultCredentials(); + prefixName = credentials.path; } else { - credentials = await this.getAWSCredentials(); + prefixName = credentials.prefixName; } const yamlFiles = fs.readdirSync(valuesDir).filter(file => @@ -390,6 +436,10 @@ export default class SetupPushSecrets extends Command { const yamlPath = path.join(valuesDir, yamlFile); this.log(chalk.cyan(`Processing ${yamlFile}`)); + // Extract sequencer index from filename if it matches the pattern + const sequencerMatch = yamlFile.match(/l2-sequencer-production-(\d+)\.yaml$/); + const sequencerIndex = sequencerMatch ? sequencerMatch[1] : null; + const content = fs.readFileSync(yamlPath, 'utf8'); const yamlContent = yaml.load(content) as any; @@ -430,21 +480,29 @@ export default class SetupPushSecrets extends Command { } } } + // Update remoteRef.key + for (const data of secret.data) { + if (data.remoteRef && data.remoteRef.key) { + // Keep the standard combined path format + let updatedKey = ""; + if (secretName.match(/^l2-sequencer-secret-\d+-env$/)) { + updatedKey = prefixName + ? `${prefixName}/l2-sequencer-secret-env` : "l2-sequencer-secret-env"; + } else { + updatedKey = prefixName + ? `${prefixName}/${secretName}` : secretName; + } - // Update remoteRef for l2-sequencer secrets - if (secretName.match(/^l2-sequencer-secret-\d+-env$/)) { - for (const data of secret.data) { - if (data.remoteRef && data.remoteRef.key) { - // Use the prefixName if available - const prefix = prefixName || (data.remoteRef.key.startsWith('scroll/') ? 'scroll' : ''); - data.remoteRef.key = `${prefix}/l2-sequencer-secret-env`; + // Only update if the key has changed + if (data.remoteRef.key !== updatedKey) { + data.remoteRef.key = updatedKey; updated = true; } } } } } - + if (updated) { const newContent = yaml.dump(yamlContent, { lineWidth: -1, noRefs: true, quotingType: '"', forceQuotes: true }); fs.writeFileSync(yamlPath, newContent); @@ -455,7 +513,6 @@ export default class SetupPushSecrets extends Command { } } - public async run(): Promise { const { flags } = await this.parse(SetupPushSecrets) this.flags = flags @@ -472,15 +529,15 @@ export default class SetupPushSecrets extends Command { let service: SecretService let provider: string - let prefixName: string | undefined + let credentials: Record if (secretService === 'aws') { - const awsCredentials = await this.getAWSCredentials() - service = new AWSSecretService(awsCredentials.secretRegion, awsCredentials.prefixName, flags.debug) + credentials = await this.getAWSCredentials() + service = new AWSSecretService(credentials.secretRegion, credentials.prefixName, flags.debug) provider = 'aws' - prefixName = awsCredentials.prefixName } else if (secretService === 'vault') { - service = new HashicorpVaultDevService(flags.debug) + credentials = await this.getVaultCredentials() + service = new HashicorpVaultDevService(flags.debug, credentials.path) provider = 'vault' } else { this.error(chalk.red('Invalid secret service selected')) @@ -495,7 +552,7 @@ export default class SetupPushSecrets extends Command { }) if (shouldUpdateYaml) { - await this.updateProductionYaml(provider, prefixName) + await this.updateProductionYaml(provider, credentials) this.log(chalk.green('Production YAML files updated successfully')) } else { this.log(chalk.yellow('Skipped updating production YAML files')) From e7228ac0939af682b641c89bdd71a9df5b1f6294 Mon Sep 17 00:00:00 2001 From: shu-unifra Date: Sun, 27 Apr 2025 08:57:01 +0000 Subject: [PATCH 3/7] fix bug of blockscout HOST --- src/commands/setup/prep-charts.ts | 78 +++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/src/commands/setup/prep-charts.ts b/src/commands/setup/prep-charts.ts index 4341e82..c38b2cc 100644 --- a/src/commands/setup/prep-charts.ts +++ b/src/commands/setup/prep-charts.ts @@ -141,35 +141,35 @@ export default class SetupPrepCharts extends Command { // if (value === '' || value === '[""]' || value === '[]' || // (Array.isArray(value) && (value.length === 0 || (value.length === 1 && value[0] === ''))) || // value === null || value === undefined) { - const configMapping = this.configMapping[key] - if (configMapping) { - let configKey: string - if (typeof configMapping === 'function') { - configKey = configMapping(chartName, productionNumber) - } else { - configKey = configMapping - } - if(chartName === "l1-devnet" && key === "CHAIN_ID"){ - configKey = "general.CHAIN_ID_L1"; - } + const configMapping = this.configMapping[key] + if (configMapping) { + let configKey: string + if (typeof configMapping === 'function') { + configKey = configMapping(chartName, productionNumber) + } else { + configKey = configMapping + } + if (chartName === "l1-devnet" && key === "CHAIN_ID") { + configKey = "general.CHAIN_ID_L1"; + } - const configValue = this.getConfigValue(configKey) - if (configValue !== undefined && configValue !== null) { - let newValue: string | string[] - if (Array.isArray(configValue)) { - newValue = JSON.stringify(configValue) - } else { - newValue = String(configValue) - } - if (newValue != value) { - changes.push({ key, oldValue: JSON.stringify(value), newValue: newValue }) - envData[key] = newValue - updated = true - } + const configValue = this.getConfigValue(configKey) + if (configValue !== undefined && configValue !== null) { + let newValue: string | string[] + if (Array.isArray(configValue)) { + newValue = JSON.stringify(configValue) } else { - this.log(chalk.yellow(`${chartName}: No value found for ${configKey}`)) + newValue = String(configValue) } + if (newValue != value) { + changes.push({ key, oldValue: JSON.stringify(value), newValue: newValue }) + envData[key] = newValue + updated = true + } + } else { + this.log(chalk.yellow(`${chartName}: No value found for ${configKey}`)) } + } //} } } @@ -243,6 +243,34 @@ export default class SetupPrepCharts extends Command { } } } + /* + blockscout-stack.blockscout.ingress.annotations.nginx.ingress.kubernetes.io/cors-allow-origin:https://blockscout.scrollsdk + blockscout-stack.blockscout.ingress.hostname:blockscout.scrollsdk + blockscout-stack.frontend.env.NEXT_PUBLIC_API_HOST:blockscout.scrollsdk + blockscout-stack.frontend.ingress.annotations.nginx.ingress.kubernetes.io/cors-allow-origin: "https://blockscout.scrollsdk" + blockscout-stack.frontend.ingress.hostname: "blockscout.scrollsdk" + */ + if (productionYaml["blockscout-stack"]) { + let ingressUpdated = false; + let blockscout_host = this.getConfigValue("ingress.BLOCKSCOUT_HOST"); + let blockscout_url = `https://${blockscout_host}`; + if (productionYaml["blockscout-stack"].blockscout.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"]) { + productionYaml["blockscout-stack"].blockscout.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"] = blockscout_url + } + + if (productionYaml["blockscout-stack"].blockscout.ingress.hostname) { + productionYaml["blockscout-stack"].blockscout.ingress.hostname = blockscout_host + } + if (productionYaml["blockscout-stack"].frontend.env.NEXT_PUBLIC_API_HOST) { + productionYaml["blockscout-stack"].frontend.env.NEXT_PUBLIC_API_HOST = blockscout_host + } + if (productionYaml["blockscout-stack"].frontend.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"]) { + productionYaml["blockscout-stack"].frontend.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"] = blockscout_url; + } + if (productionYaml["blockscout-stack"].frontend.ingress.hostname) { + productionYaml["blockscout-stack"].frontend.ingress.hostname = blockscout_host + } + } if (productionYaml.grafana) { let ingressUpdated = false; From b65fbc27fff2be8ef78cfb29e5faea4cf78a8a92 Mon Sep 17 00:00:00 2001 From: shu-unifra Date: Sun, 27 Apr 2025 09:41:40 +0000 Subject: [PATCH 4/7] fix bug blockscout ingress --- src/commands/setup/prep-charts.ts | 39 ++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/commands/setup/prep-charts.ts b/src/commands/setup/prep-charts.ts index c38b2cc..b38c397 100644 --- a/src/commands/setup/prep-charts.ts +++ b/src/commands/setup/prep-charts.ts @@ -252,23 +252,40 @@ export default class SetupPrepCharts extends Command { */ if (productionYaml["blockscout-stack"]) { let ingressUpdated = false; + const blockscout = productionYaml["blockscout-stack"].blockscout; + const frontend = productionYaml["blockscout-stack"].frontend; let blockscout_host = this.getConfigValue("ingress.BLOCKSCOUT_HOST"); - let blockscout_url = `https://${blockscout_host}`; - if (productionYaml["blockscout-stack"].blockscout.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"]) { - productionYaml["blockscout-stack"].blockscout.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"] = blockscout_url + let blockscout_url = this.getConfigValue("frontend.EXTERNAL_EXPLORER_URI_L2"); + + if (blockscout?.ingress?.annotations?.["nginx.ingress.kubernetes.io/cors-allow-origin"]) { + changes.push({ key: `ingress.blockscout.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"]`, oldValue: blockscout.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"], newValue: blockscout_url }); + blockscout.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"] = blockscout_url; + ingressUpdated = true; } - if (productionYaml["blockscout-stack"].blockscout.ingress.hostname) { - productionYaml["blockscout-stack"].blockscout.ingress.hostname = blockscout_host + if (blockscout?.ingress?.hostname) { + changes.push({ key: `ingress.blockscout.hostname`, oldValue: blockscout.ingress.hostname, newValue: blockscout_host }); + blockscout.ingress.hostname = blockscout_host; + ingressUpdated = true; + } + if (frontend?.env?.NEXT_PUBLIC_API_HOST) { + changes.push({ key: `frontend.env.NEXT_PUBLIC_API_HOST`, oldValue: frontend.env.NEXT_PUBLIC_API_HOST, newValue: blockscout_host }); + frontend.env.NEXT_PUBLIC_API_HOST = blockscout_host; + ingressUpdated = true; } - if (productionYaml["blockscout-stack"].frontend.env.NEXT_PUBLIC_API_HOST) { - productionYaml["blockscout-stack"].frontend.env.NEXT_PUBLIC_API_HOST = blockscout_host + if (frontend?.ingress?.annotations?.["nginx.ingress.kubernetes.io/cors-allow-origin"]) { + changes.push({ key: `frontend.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"]`, oldValue: frontend.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"], newValue: blockscout_url }); + frontend.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"] = blockscout_url; + ingressUpdated = true; } - if (productionYaml["blockscout-stack"].frontend.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"]) { - productionYaml["blockscout-stack"].frontend.ingress.annotations["nginx.ingress.kubernetes.io/cors-allow-origin"] = blockscout_url; + if (frontend?.ingress?.hostname) { + changes.push({ key: `frontend.ingress.hostname`, oldValue: frontend.ingress.hostname, newValue: blockscout_host }); + frontend.ingress.hostname = blockscout_host; + ingressUpdated = true; } - if (productionYaml["blockscout-stack"].frontend.ingress.hostname) { - productionYaml["blockscout-stack"].frontend.ingress.hostname = blockscout_host + + if (ingressUpdated) { + updated = true; } } From c45b8851b73c025c821bde5c411248ef9ad40c93 Mon Sep 17 00:00:00 2001 From: shu-unifra Date: Sun, 27 Apr 2025 23:46:40 +0000 Subject: [PATCH 5/7] fix bug blockscout INDEX_* not init --- src/commands/setup/prep-charts.ts | 82 +++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/commands/setup/prep-charts.ts b/src/commands/setup/prep-charts.ts index b38c397..f264460 100644 --- a/src/commands/setup/prep-charts.ts +++ b/src/commands/setup/prep-charts.ts @@ -113,6 +113,8 @@ export default class SetupPrepCharts extends Command { } private async processProductionYaml(valuesDir: string): Promise<{ updated: number; skipped: number }> { + + const productionFiles = fs.readdirSync(valuesDir) .filter(file => file.endsWith('-production.yaml') || file.match(/-production-\d+\.yaml$/)) @@ -283,6 +285,86 @@ export default class SetupPrepCharts extends Command { frontend.ingress.hostname = blockscout_host; ingressUpdated = true; } + /* + INDEXER_SCROLL_L1_CHAIN_CONTRACT: "" + INDEXER_SCROLL_L1_BATCH_START_BLOCK: "" + INDEXER_SCROLL_L1_MESSENGER_CONTRACT: "" + INDEXER_SCROLL_L1_MESSENGER_START_BLOCK: "" + INDEXER_SCROLL_L2_MESSENGER_CONTRACT: "" + INDEXER_SCROLL_L2_GAS_ORACLE_CONTRACT: "" + INDEXER_SCROLL_L1_RPC: "" + INDEXER_SCROLL_L2_MESSENGER_START_BLOCK: 0 + INDEXER_SCROLL_L1_ETH_GET_LOGS_RANGE_SIZE: 500 + INDEXER_SCROLL_L2_ETH_GET_LOGS_RANGE_SIZE: 500 + */ + interface BlockscoutEnvMapping { + key: string; + configKey: string; + defaultValue?: string; + } + + const BLOCKSCOUT_ENV_MAPPINGS: BlockscoutEnvMapping[] = [ + { + key: 'INDEXER_SCROLL_L1_BATCH_START_BLOCK', + configKey: '', + defaultValue: '0' + }, + { + key: 'INDEXER_SCROLL_L1_MESSENGER_START_BLOCK', + configKey: '', + defaultValue: '0' + }, + { + key: 'INDEXER_SCROLL_L1_CHAIN_CONTRACT', + configKey: 'contractsFile.L1_SCROLL_CHAIN_PROXY_ADDR' + }, + { + key: 'INDEXER_SCROLL_L1_MESSENGER_CONTRACT', + configKey: 'L1_SCROLL_MESSENGER_PROXY_ADDR' + }, + { + key: 'INDEXER_SCROLL_L2_MESSENGER_CONTRACT', + configKey: 'L2_SCROLL_MESSENGER_PROXY_ADDR' + }, + { + key: 'INDEXER_SCROLL_L2_GAS_ORACLE_CONTRACT', + configKey: 'L1_GAS_PRICE_ORACLE_ADDR' + }, + { + key: 'INDEXER_SCROLL_L1_RPC', + configKey: 'general.L1_RPC_ENDPOINT' + }, + { + key: 'INDEXER_SCROLL_L1_RPC', + configKey: 'L1_RPC_ENDPOINT', + defaultValue: '0' + } + + + ]; + const benv = productionYaml["blockscout-stack"].blockscout.env; + + BLOCKSCOUT_ENV_MAPPINGS.forEach(mapping => { + const { key, configKey, defaultValue } = mapping; + + let newValue = this.getConfigValue(configKey); + if (!newValue) { + newValue = configKey ? this.contractsConfig[configKey] : defaultValue; + } + + if (newValue !== undefined) { + changes.push({ + key: `blockscout.env.${key}`, + oldValue: benv[key], + newValue: newValue + }); + benv[key] = newValue; + } else { + this.log(chalk.yellow(`No value found for ${key}`)); + } + }); + + updated = true; if (ingressUpdated) { updated = true; From abe7738ff628fd5ce751ccba40a61edf02b192e5 Mon Sep 17 00:00:00 2001 From: shu-unifra Date: Tue, 29 Apr 2025 07:05:18 +0000 Subject: [PATCH 6/7] fix bug: should auto generate values in contracts.verification --- src/commands/setup/db-init.ts | 2 +- src/commands/setup/domains.ts | 17 +++++++++++++++++ src/commands/setup/prep-charts.ts | 5 ----- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/commands/setup/db-init.ts b/src/commands/setup/db-init.ts index 8074a55..05ed3b0 100644 --- a/src/commands/setup/db-init.ts +++ b/src/commands/setup/db-init.ts @@ -377,7 +377,7 @@ export default class SetupDbInit extends Command { this.log(chalk.blue('First, provide connection information for the database instance. This will only be used for creating users and databases. This information will not be persisted in your configuration repo.')); const publicHost = await input({ message: 'Enter public PostgreSQL host:', default: 'localhost' }) const publicPort = await input({ message: 'Enter public PostgreSQL port:', default: '5432' }) - const pgUser = await input({ message: 'Enter PostgreSQL admin username:', default: 'admin' }) + const pgUser = await input({ message: 'Enter PostgreSQL admin username:', default: 'scrolladmin' }) const pgPassword = await password({ message: 'Enter PostgreSQL admin password:' }) const pgDatabase = await input({ message: 'Enter PostgreSQL database name:', default: 'postgres' }) diff --git a/src/commands/setup/domains.ts b/src/commands/setup/domains.ts index 61d705f..21f4a1e 100644 --- a/src/commands/setup/domains.ts +++ b/src/commands/setup/domains.ts @@ -457,6 +457,23 @@ export default class SetupDomains extends Command { delete existingConfig.ingress.L1_EXPLORER_HOST } + /* + [contracts.verification] + VERIFIER_TYPE_L1 = "blockscout" + VERIFIER_TYPE_L2 = "blockscout" + EXPLORER_URI_L1 = "http://l1-explorer.scrollsdk" + EXPLORER_URI_L2 = "http://blockscout.scrollsdk" + RPC_URI_L1 = "http://l1-devnet.scrollsdk" + RPC_URI_L2 = "http://l2-rpc.scrollsdk" + EXPLORER_API_KEY_L1 = "" + EXPLORER_API_KEY_L2 = "" + */ + existingConfig.contracts.verification.EXPLORER_URI_L1 = domainConfig.EXTERNAL_EXPLORER_URI_L1; + existingConfig.contracts.verification.EXPLORER_URI_L2 = domainConfig.EXTERNAL_EXPLORER_URI_L2; + existingConfig.contracts.verification.RPC_URI_L1 = domainConfig.EXTERNAL_RPC_URI_L1; + existingConfig.contracts.verification.RPC_URI_L2 = domainConfig.EXTERNAL_RPC_URI_L2; + + // Convert the updated config back to TOML string const updatedContent = toml.stringify(existingConfig) diff --git a/src/commands/setup/prep-charts.ts b/src/commands/setup/prep-charts.ts index f264460..533567a 100644 --- a/src/commands/setup/prep-charts.ts +++ b/src/commands/setup/prep-charts.ts @@ -333,11 +333,6 @@ export default class SetupPrepCharts extends Command { { key: 'INDEXER_SCROLL_L1_RPC', configKey: 'general.L1_RPC_ENDPOINT' - }, - { - key: 'INDEXER_SCROLL_L1_RPC', - configKey: 'L1_RPC_ENDPOINT', - defaultValue: '0' } From 942454e98bd3001ab9f05ae911b829523f9d69eb Mon Sep 17 00:00:00 2001 From: shu-unifra Date: Wed, 30 Apr 2025 11:45:47 +0000 Subject: [PATCH 7/7] Vault path cannot be all numeric --- src/commands/setup/push-secrets.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/commands/setup/push-secrets.ts b/src/commands/setup/push-secrets.ts index 8faf973..d6227ca 100644 --- a/src/commands/setup/push-secrets.ts +++ b/src/commands/setup/push-secrets.ts @@ -383,7 +383,13 @@ export default class SetupPushSecrets extends Command { }), path: await input({ message: chalk.cyan('Enter Vault path:'), - default: "scroll" + default: "scroll", + validate: (value: string) => { + if (/^\d+$/.test(value)) { + return 'Path cannot be all numeric'; + } + return true; + } }), version: await input({ message: chalk.cyan('Enter Vault version:'),