mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
ENVs changes and test script for validator (#1296)
* use SENTRY_CSP_REPORT_URI only in nextjs part of the app * rename NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY to FAVICON_GENERATOR_API_KEY * tests presets for envs validator * simplify logs * refactor getExternalJsonContent function * tweak contribution guide * break validator * debug workflow * fix copying assets folder * fix CI
This commit is contained in:
+1
-1
@@ -5,4 +5,4 @@ NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
|
||||
NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID=UA-XXXXXX-X
|
||||
NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN=xxx
|
||||
NEXT_PUBLIC_AUTH0_CLIENT_ID=xxx
|
||||
NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY=xxx
|
||||
FAVICON_GENERATOR_API_KEY=xxx
|
||||
+1
-1
@@ -305,7 +305,7 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
{
|
||||
files: [ '*.config.ts', 'playwright/**', 'deploy/tools/**', 'middleware.ts' ],
|
||||
files: [ '*.config.ts', 'playwright/**', 'deploy/tools/**', 'middleware.ts', 'nextjs/**' ],
|
||||
rules: {
|
||||
// for configs allow to consume env variables from process.env directly
|
||||
'no-restricted-properties': [ 0 ],
|
||||
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
run: yarn lint:tsc
|
||||
|
||||
envs_validation:
|
||||
name: ENV variables presets validation
|
||||
name: ENV variables validation
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ code_quality ]
|
||||
steps:
|
||||
@@ -80,13 +80,10 @@ jobs:
|
||||
- name: Install script dependencies
|
||||
run: cd ./deploy/tools/envs-validator && yarn --frozen-lockfile --ignore-optional
|
||||
|
||||
- name: Copy secrets file
|
||||
run: cp ./.env.example ./configs/envs/.env.secrets
|
||||
|
||||
- name: Run validation script
|
||||
- name: Run validation tests
|
||||
run: |
|
||||
set +e
|
||||
cd ./deploy/tools/envs-validator && yarn dev
|
||||
cd ./deploy/tools/envs-validator && yarn test
|
||||
exitcode="$?"
|
||||
echo "exitcode=$exitcode" >> $GITHUB_OUTPUT
|
||||
exit "$exitcode"
|
||||
|
||||
@@ -14,25 +14,10 @@ const instance = (() => {
|
||||
})();
|
||||
const environment = getEnvValue('NEXT_PUBLIC_APP_ENV') || 'production';
|
||||
const release = getEnvValue('NEXT_PUBLIC_GIT_TAG');
|
||||
const cspReportUrl = (() => {
|
||||
try {
|
||||
const url = new URL(getEnvValue('SENTRY_CSP_REPORT_URI') || '');
|
||||
|
||||
// https://docs.sentry.io/product/security-policy-reporting/#additional-configuration
|
||||
url.searchParams.set('sentry_environment', environment);
|
||||
release && url.searchParams.set('sentry_release', release);
|
||||
|
||||
return url.toString();
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
|
||||
const title = 'Sentry error monitoring';
|
||||
|
||||
const config: Feature<{
|
||||
dsn: string;
|
||||
cspReportUrl: string | undefined;
|
||||
instance: string;
|
||||
release: string | undefined;
|
||||
environment: string;
|
||||
@@ -42,7 +27,6 @@ const config: Feature<{
|
||||
title,
|
||||
isEnabled: true,
|
||||
dsn,
|
||||
cspReportUrl,
|
||||
instance,
|
||||
release,
|
||||
environment,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
master_url="${NEXT_PUBLIC_FAVICON_MASTER_URL:-$NEXT_PUBLIC_NETWORK_ICON}"
|
||||
master_url="${FAVICON_MASTER_URL:-$NEXT_PUBLIC_NETWORK_ICON}"
|
||||
export MASTER_URL="$master_url"
|
||||
|
||||
cd ./deploy/tools/favicon-generator
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
/public
|
||||
.env
|
||||
.env.registry
|
||||
.env.secrets
|
||||
index.js
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
export NEXT_PUBLIC_GIT_COMMIT_SHA=$(git rev-parse --short HEAD)
|
||||
export NEXT_PUBLIC_GIT_TAG=$(git describe --tags --abbrev=0)
|
||||
../../scripts/collect_envs.sh ../../../docs/ENVS.md
|
||||
|
||||
yarn build
|
||||
|
||||
PRESETS=(
|
||||
"main"
|
||||
"main.L2"
|
||||
)
|
||||
|
||||
validate_preset() {
|
||||
local preset="$1"
|
||||
secrets_file="../../../configs/envs/.env.secrets"
|
||||
config_file="../../../configs/envs/.env.${preset}"
|
||||
|
||||
echo
|
||||
echo "------------------------------------------------"
|
||||
echo "🧿 Validating preset '$preset'..."
|
||||
|
||||
dotenv \
|
||||
-e $config_file \
|
||||
-- bash -c '../../scripts/download_assets.sh ./public/assets'
|
||||
|
||||
dotenv \
|
||||
-e $config_file \
|
||||
-e $secrets_file \
|
||||
yarn validate
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ Preset '$preset' is valid."
|
||||
echo "------------------------------------------------"
|
||||
echo
|
||||
return 0
|
||||
else
|
||||
echo "🛑 Preset '$preset' is invalid. Please fix it and run script again."
|
||||
echo "------------------------------------------------"
|
||||
echo
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
for preset in "${PRESETS[@]}"; do
|
||||
validate_preset "$preset"
|
||||
if [ $? -eq 1 ]; then
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
@@ -3,12 +3,15 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
import type { ValidationError } from 'yup';
|
||||
|
||||
import { buildExternalAssetFilePath } from '../../../configs/app/utils';
|
||||
import schema from './schema';
|
||||
|
||||
const silent = process.argv.includes('--silent');
|
||||
|
||||
run();
|
||||
|
||||
async function run() {
|
||||
console.log();
|
||||
!silent && console.log();
|
||||
try {
|
||||
const appEnvs = Object.entries(process.env)
|
||||
.filter(([ key ]) => key.startsWith('NEXT_PUBLIC_'))
|
||||
@@ -26,25 +29,22 @@ async function run() {
|
||||
}
|
||||
|
||||
async function validateEnvs(appEnvs: Record<string, string>) {
|
||||
console.log(`🌀 Validating ENV variables values...`);
|
||||
!silent && console.log(`🌀 Validating ENV variables values...`);
|
||||
|
||||
try {
|
||||
// replace ENVs with external JSON files content
|
||||
appEnvs.NEXT_PUBLIC_FEATURED_NETWORKS = await getExternalJsonContent(
|
||||
'./public/assets/featured_networks.json',
|
||||
appEnvs.NEXT_PUBLIC_FEATURED_NETWORKS,
|
||||
) || '[]';
|
||||
appEnvs.NEXT_PUBLIC_MARKETPLACE_CONFIG_URL = await getExternalJsonContent(
|
||||
'./public/assets/marketplace_config.json',
|
||||
appEnvs.NEXT_PUBLIC_MARKETPLACE_CONFIG_URL,
|
||||
) || '[]';
|
||||
appEnvs.NEXT_PUBLIC_FOOTER_LINKS = await getExternalJsonContent(
|
||||
'./public/assets/footer_links.json',
|
||||
appEnvs.NEXT_PUBLIC_FOOTER_LINKS,
|
||||
) || '[]';
|
||||
const envsWithJsonConfig = [
|
||||
'NEXT_PUBLIC_FEATURED_NETWORKS',
|
||||
'NEXT_PUBLIC_MARKETPLACE_CONFIG_URL',
|
||||
'NEXT_PUBLIC_FOOTER_LINKS',
|
||||
];
|
||||
|
||||
for await (const envName of envsWithJsonConfig) {
|
||||
appEnvs[envName] = await(appEnvs[envName] ? getExternalJsonContent(envName) : Promise.resolve()) || '[]';
|
||||
}
|
||||
|
||||
await schema.validate(appEnvs, { stripUnknown: false, abortEarly: false });
|
||||
console.log('👍 All good!');
|
||||
!silent && console.log('👍 All good!');
|
||||
} catch (_error) {
|
||||
if (typeof _error === 'object' && _error !== null && 'errors' in _error) {
|
||||
console.log('🚨 ENVs validation failed with the following errors:');
|
||||
@@ -59,15 +59,12 @@ async function validateEnvs(appEnvs: Record<string, string>) {
|
||||
throw _error;
|
||||
}
|
||||
|
||||
console.log();
|
||||
!silent && console.log();
|
||||
}
|
||||
|
||||
async function getExternalJsonContent(fileName: string, envValue: string): Promise<string | void> {
|
||||
async function getExternalJsonContent(envName: string): Promise<string | void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!envValue) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const fileName = `./public${ buildExternalAssetFilePath(envName, '.json') }`;
|
||||
|
||||
fs.readFile(path.resolve(__dirname, fileName), 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
@@ -83,7 +80,7 @@ async function getExternalJsonContent(fileName: string, envValue: string): Promi
|
||||
|
||||
async function checkPlaceholdersCongruity(envsMap: Record<string, string>) {
|
||||
try {
|
||||
console.log(`🌀 Checking environment variables and their placeholders congruity...`);
|
||||
!silent && console.log(`🌀 Checking environment variables and their placeholders congruity...`);
|
||||
|
||||
const runTimeEnvs = await getEnvsPlaceholders(path.resolve(__dirname, '.env.registry'));
|
||||
const buildTimeEnvs = await getEnvsPlaceholders(path.resolve(__dirname, '.env'));
|
||||
@@ -108,7 +105,7 @@ async function checkPlaceholdersCongruity(envsMap: Record<string, string>) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
console.log('👍 All good!\n');
|
||||
!silent && console.log('👍 All good!\n');
|
||||
} catch (error) {
|
||||
console.log('🚨 Congruity check failed.\n');
|
||||
throw error;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"build": "yarn webpack-cli -c ./webpack.config.js",
|
||||
"validate": "node ./index.js",
|
||||
"dev": "./dev.sh"
|
||||
"test": "./test.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"ts-loader": "^9.4.4",
|
||||
|
||||
@@ -438,7 +438,6 @@ const schema = yup
|
||||
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY: yup.string(),
|
||||
NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: yup.string(),
|
||||
NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN: yup.string(),
|
||||
NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY: yup.string(),
|
||||
|
||||
// Misc
|
||||
NEXT_PUBLIC_USE_NEXT_JS_PROXY: yup.boolean(),
|
||||
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
|
||||
secrets_file=".env.secrets"
|
||||
test_folder="./test"
|
||||
common_file="${test_folder}/.env.common"
|
||||
|
||||
# Generate ENV registry file
|
||||
export NEXT_PUBLIC_GIT_COMMIT_SHA=$(git rev-parse --short HEAD)
|
||||
export NEXT_PUBLIC_GIT_TAG=$(git describe --tags --abbrev=0)
|
||||
../../scripts/collect_envs.sh ../../../docs/ENVS.md
|
||||
cp ../../../.env.example ${secrets_file}
|
||||
|
||||
# Copy test assets
|
||||
mkdir -p "./public/assets"
|
||||
cp -r ${test_folder}/assets ./public/
|
||||
|
||||
# Build validator script
|
||||
yarn build
|
||||
|
||||
validate_file() {
|
||||
local test_file="$1"
|
||||
|
||||
echo
|
||||
echo "🧿 Validating file '$test_file'..."
|
||||
|
||||
dotenv \
|
||||
-e $test_file \
|
||||
-e $common_file \
|
||||
-e $secrets_file \
|
||||
yarn run validate -- --silent
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "👍 All good!"
|
||||
return 0
|
||||
else
|
||||
echo "🛑 The file is invalid. Please fix errors and run script again."
|
||||
echo
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
test_files=($(find "$test_folder" -maxdepth 1 -type f | grep -vE '\/\.env\.common$'))
|
||||
|
||||
for file in "${test_files[@]}"; do
|
||||
validate_file "$file"
|
||||
if [ $? -eq 1 ]; then
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,3 @@
|
||||
NEXT_PUBLIC_AD_BANNER_PROVIDER=adbutler
|
||||
NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP={'id':'123456','width':'728','height':'90'}
|
||||
NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE={'id':'654321','width':'300','height':'100'}
|
||||
@@ -0,0 +1,52 @@
|
||||
NEXT_PUBLIC_AD_TEXT_PROVIDER=coinzilla
|
||||
NEXT_PUBLIC_AD_BANNER_PROVIDER=slise
|
||||
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://example.com
|
||||
NEXT_PUBLIC_API_BASE_PATH=/
|
||||
NEXT_PUBLIC_API_SPEC_URL=https://example.com
|
||||
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
|
||||
NEXT_PUBLIC_APP_ENV=development
|
||||
NEXT_PUBLIC_APP_PORT=3000
|
||||
NEXT_PUBLIC_APP_PROTOCOL=http
|
||||
NEXT_PUBLIC_BRIDGED_TOKENS_CHAINS=[{'id':'1','title':'Ethereum','short_title':'ETH','base_url':'https://example.com'}]
|
||||
NEXT_PUBLIC_BRIDGED_TOKENS_BRIDGES=[{'type':'omni','title':'OmniBridge','short_title':'OMNI'}]
|
||||
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://example.com
|
||||
NEXT_PUBLIC_FEATURED_NETWORKS=https://example.com
|
||||
NEXT_PUBLIC_FOOTER_LINKS=https://example.com
|
||||
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
|
||||
NEXT_PUBLIC_HIDE_INDEXING_ALERT=false
|
||||
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
|
||||
NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR='#fff'
|
||||
NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND='rgb(255, 145, 0)'
|
||||
NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER=true
|
||||
NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME=true
|
||||
NEXT_PUBLIC_IS_TESTNET=true
|
||||
NEXT_PUBLIC_MARKETPLACE_CONFIG_URL=https://example.com
|
||||
NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://example.com
|
||||
NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE='<a href="#">Hello</a>'
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
|
||||
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Explorer','baseUrl':'https://example.com/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]
|
||||
NEXT_PUBLIC_NETWORK_GOVERNANCE_TOKEN_SYMBOL=gETH
|
||||
NEXT_PUBLIC_NETWORK_ICON=https://example.com/icon.png
|
||||
NEXT_PUBLIC_NETWORK_ICON_DARK=https://example.com/icon.png
|
||||
NEXT_PUBLIC_NETWORK_LOGO=https://example.com/logo.png
|
||||
NEXT_PUBLIC_NETWORK_LOGO_DARK=https://example.com/logo.png
|
||||
NEXT_PUBLIC_NETWORK_RPC_URL=https://example.com
|
||||
NEXT_PUBLIC_NETWORK_SHORT_NAME=Test
|
||||
NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
|
||||
NEXT_PUBLIC_OG_DESCRIPTION='Hello world!'
|
||||
NEXT_PUBLIC_OG_IMAGE_URL=https://example.com/image.png
|
||||
NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://blockscout.com','text':'Blockscout'}]
|
||||
NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE=true
|
||||
NEXT_PUBLIC_STATS_API_HOST=https://example.com
|
||||
NEXT_PUBLIC_USE_NEXT_JS_PROXY=false
|
||||
NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE=gradient_avatar
|
||||
NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS=['top_accounts']
|
||||
NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=['burnt_fees','total_reward']
|
||||
NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'NFT Marketplace','collection_url':'https://example.com/{hash}','instance_url':'https://example.com/{hash}/{id}','logo_url':'https://example.com/logo.png'}]
|
||||
NEXT_PUBLIC_VIEWS_TX_ADDITIONAL_FIELDS=['fee_per_gas']
|
||||
NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS=['value','fee_currency','gas_price','tx_fee','gas_fees','burnt_fees']
|
||||
NEXT_PUBLIC_VISUALIZE_API_HOST=https://example.com
|
||||
NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET=false
|
||||
NEXT_PUBLIC_WEB3_WALLETS=['coinbase','metamask','token_pocket']
|
||||
@@ -0,0 +1,2 @@
|
||||
NEXT_PUBLIC_HAS_BEACON_CHAIN=true
|
||||
NEXT_PUBLIC_BEACON_CHAIN_CURRENCY_SYMBOL=aETH
|
||||
@@ -0,0 +1,7 @@
|
||||
NEXT_PUBLIC_API_HOST=blockscout.com
|
||||
NEXT_PUBLIC_APP_HOST=localhost
|
||||
NEXT_PUBLIC_AUTH_URL=https://example.com
|
||||
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
|
||||
NEXT_PUBLIC_LOGOUT_URL=https://example.com
|
||||
NEXT_PUBLIC_NETWORK_ID=1
|
||||
NEXT_PUBLIC_NETWORK_NAME=Testnet
|
||||
@@ -0,0 +1,3 @@
|
||||
NEXT_PUBLIC_IS_L2_NETWORK=true
|
||||
NEXT_PUBLIC_L1_BASE_URL=https://example.com
|
||||
NEXT_PUBLIC_L2_WITHDRAWAL_URL=https://example.com
|
||||
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"title": "Ethereum",
|
||||
"url": "https://eth.blockscout.com/",
|
||||
"group": "Mainnets",
|
||||
"icon": "https://example.com/logo.svg"
|
||||
},
|
||||
{
|
||||
"title": "Goerli",
|
||||
"url": "https://eth-goerli.blockscout.com/",
|
||||
"group": "Testnets",
|
||||
"isActive": true,
|
||||
"icon": "https://example.com/logo.svg",
|
||||
"invertIconInDarkMode": true
|
||||
},
|
||||
{
|
||||
"title": "POA Sokol",
|
||||
"url": "https://blockscout.com/poa/sokol",
|
||||
"group": "Other",
|
||||
"icon": "https://example.com/logo.svg"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,28 @@
|
||||
[
|
||||
{
|
||||
"title": "Foo",
|
||||
"links": [
|
||||
{
|
||||
"text": "Home",
|
||||
"url": "https://example.com"
|
||||
},
|
||||
{
|
||||
"text": "Brand",
|
||||
"url": "https://example.com"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Developers",
|
||||
"links": [
|
||||
{
|
||||
"text": "Develop",
|
||||
"url": "https://example.com"
|
||||
},
|
||||
{
|
||||
"text": "Grants",
|
||||
"url": "https://example.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
[
|
||||
{
|
||||
"author": "Hop",
|
||||
"id": "hop-exchange",
|
||||
"title": "Hop",
|
||||
"logo": "https://example.com/logo.svg",
|
||||
"categories": ["Bridge"],
|
||||
"shortDescription": "Hop is a scalable rollup-to-rollup general token bridge.",
|
||||
"site": "https://example.com",
|
||||
"description": "Hop is a scalable rollup-to-rollup general token bridge.",
|
||||
"external": true,
|
||||
"url": "https://example.com"
|
||||
},
|
||||
{
|
||||
"author": "Blockscout",
|
||||
"id": "token-approval-tracker",
|
||||
"title": "Token Approval Tracker",
|
||||
"logo": "https://example.com/logo.svg",
|
||||
"categories": ["Infra & Dev tooling"],
|
||||
"shortDescription": "Token Approval Tracker shows all approvals for any ERC20-compliant tokens and NFTs and lets to revoke them or adjust the approved amount.",
|
||||
"site": "https://example.com",
|
||||
"description": "Token Approval Tracker shows all approvals for any ERC20-compliant tokens and NFTs and lets to revoke them or adjust the approved amount.",
|
||||
"url": "https://example.com"
|
||||
}
|
||||
]
|
||||
@@ -8,7 +8,13 @@
|
||||
"nextjs-routes": ["./nextjs/nextjs-routes.d.ts"],
|
||||
}
|
||||
},
|
||||
"include": [ "../../../types/**/*.ts", "../../../global.d.ts", "./index.ts", "./schema.ts" ],
|
||||
"include": [
|
||||
"../../../types/**/*.ts",
|
||||
"../../../configs/app/**/*.ts",
|
||||
"../../../global.d.ts",
|
||||
"./index.ts",
|
||||
"./schema.ts"
|
||||
],
|
||||
"tsc-alias": {
|
||||
"verbose": true,
|
||||
"resolveFullPaths": true,
|
||||
|
||||
@@ -8,17 +8,17 @@ if [ -z "$MASTER_URL" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY is provided
|
||||
if [ -z "$NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY" ]; then
|
||||
echo "🛑 Error: NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY variable is not provided."
|
||||
# Check if FAVICON_GENERATOR_API_KEY is provided
|
||||
if [ -z "$FAVICON_GENERATOR_API_KEY" ]; then
|
||||
echo "🛑 Error: FAVICON_GENERATOR_API_KEY variable is not provided."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Mask the NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY to display only the first 8 characters
|
||||
API_KEY_MASKED="${NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY:0:8}***"
|
||||
# Mask the FAVICON_GENERATOR_API_KEY to display only the first 8 characters
|
||||
API_KEY_MASKED="${FAVICON_GENERATOR_API_KEY:0:8}***"
|
||||
echo "🆗 The following variables are provided:"
|
||||
echo " MASTER_URL: $MASTER_URL"
|
||||
echo " NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY: $API_KEY_MASKED"
|
||||
echo " FAVICON_GENERATOR_API_KEY: $API_KEY_MASKED"
|
||||
echo
|
||||
|
||||
# RealFaviconGenerator API endpoint URL
|
||||
@@ -34,7 +34,7 @@ CONFIG_TEMPLATE_FILE="config.template.json"
|
||||
CONFIG_FILE="config.json"
|
||||
|
||||
# Replace <api_key> and <master_url> placeholders in the JSON template file
|
||||
API_KEY_VALUE="$NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY"
|
||||
API_KEY_VALUE="$FAVICON_GENERATOR_API_KEY"
|
||||
sed -e "s|<api_key>|$API_KEY_VALUE|" -e "s|<master_url>|$MASTER_URL|" "$CONFIG_TEMPLATE_FILE" > "$CONFIG_FILE"
|
||||
|
||||
# Make the API POST request with JSON data from the config file
|
||||
|
||||
@@ -203,4 +203,4 @@ frontend:
|
||||
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID
|
||||
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY
|
||||
NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID
|
||||
NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY
|
||||
FAVICON_GENERATOR_API_KEY: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY
|
||||
|
||||
@@ -167,4 +167,4 @@ frontend:
|
||||
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID
|
||||
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY
|
||||
NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID
|
||||
NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY
|
||||
FAVICON_GENERATOR_API_KEY: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY
|
||||
|
||||
@@ -144,7 +144,7 @@ frontend:
|
||||
_default: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY
|
||||
NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID:
|
||||
_default: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID
|
||||
NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY:
|
||||
FAVICON_GENERATOR_API_KEY:
|
||||
_default: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY
|
||||
NEXT_PUBLIC_OG_IMAGE_URL:
|
||||
_default: https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/base-goerli.png?raw=true
|
||||
|
||||
@@ -129,7 +129,7 @@ frontend:
|
||||
_default: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY
|
||||
NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID:
|
||||
_default: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID
|
||||
NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY:
|
||||
FAVICON_GENERATOR_API_KEY:
|
||||
_default: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY
|
||||
NEXT_PUBLIC_WEB3_WALLETS:
|
||||
_default: "['token_pocket','coinbase','metamask']"
|
||||
|
||||
@@ -81,13 +81,17 @@ These are the steps that you have to follow to make everything work:
|
||||
- `deploy/values/main/values.yaml` - main development environment
|
||||
- `deploy/values/review-l2/values.yaml.gotmpl` - review development environment for L2 networks
|
||||
- `deploy/values/l2-optimism-goerli/values.yaml` - main development environment
|
||||
5. Add validation schema for the new variable into the file `deploy/tools/envs-validator/schema.ts`; verify that any or all updated config presets from "Step 3" are valid by doing the following steps:
|
||||
5. If your variable is meant to receive a link to some external resource (image or JSON-config file), extend the array `ASSETS_ENVS` in `deploy/scripts/download_assets.sh` with your variable name
|
||||
6. Add validation schema for the new variable into the file `deploy/tools/envs-validator/schema.ts`
|
||||
7. Check if modified validation schema is valid by doing the following steps:
|
||||
- change your current directory to `deploy/tools/envs-validator`
|
||||
- install deps with `yarn` command
|
||||
- change `PRESETS` array in `dev.sh` script file accordingly
|
||||
- run `yarn dev` command and see the validation result
|
||||
- *Please* do not commit your changes in the `dev.sh` file since it is also used in the CI workflow
|
||||
6. Don't forget to mention in the PR notes that new ENV variable was added
|
||||
- add your variable into `./test/.env.base` test preset or create a new test preset if needed
|
||||
- if your variable contains a link to the external JSON config file:
|
||||
- add example of file content into `./test/assets` directory; the file name should be constructed by stripping away prefix `NEXT_PUBLIC_` and postfix `_URL` if any, and converting the remaining string to lowercase (for example, `NEXT_PUBLIC_MARKETPLACE_CONFIG_URL` will become `marketplace_config.json`)
|
||||
- in the main script `index.ts` extend array `envsWithJsonConfig` with your variable name
|
||||
- run `yarn test` command to see the validation result
|
||||
8. Don't forget to mention in the PR notes that new ENV variable was added
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -148,8 +148,8 @@ By default, the app has generic favicon. You can override this behavior by provi
|
||||
|
||||
| Variable | Type| Description | Compulsoriness | Default value | Example value |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY | `string` | RealFaviconGenerator [API key](https://realfavicongenerator.net/api/) | Required | - | `<your-secret>` |
|
||||
| NEXT_PUBLIC_FAVICON_MASTER_URL | `string` | - | - | `NEXT_PUBLIC_NETWORK_ICON` | `https://placekitten.com/180/180` |
|
||||
| FAVICON_GENERATOR_API_KEY | `string` | RealFaviconGenerator [API key](https://realfavicongenerator.net/api/) | Required | - | `<your-secret>` |
|
||||
| FAVICON_MASTER_URL | `string` | - | - | `NEXT_PUBLIC_NETWORK_ICON` | `https://placekitten.com/180/180` |
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,25 @@ const MAIN_DOMAINS = [
|
||||
getFeaturePayload(config.features.sol2uml)?.api.endpoint,
|
||||
].filter(Boolean);
|
||||
|
||||
const getCspReportUrl = () => {
|
||||
try {
|
||||
const sentryFeature = config.features.sentry;
|
||||
if (!sentryFeature.isEnabled || !process.env.SENTRY_CSP_REPORT_URI) {
|
||||
return;
|
||||
}
|
||||
|
||||
const url = new URL(process.env.SENTRY_CSP_REPORT_URI);
|
||||
|
||||
// https://docs.sentry.io/product/security-policy-reporting/#additional-configuration
|
||||
url.searchParams.set('sentry_environment', sentryFeature.environment);
|
||||
sentryFeature.release && url.searchParams.set('sentry_release', sentryFeature.release);
|
||||
|
||||
return url.toString();
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
export function app(): CspDev.DirectiveDescriptor {
|
||||
return {
|
||||
'default-src': [
|
||||
@@ -110,15 +129,14 @@ export function app(): CspDev.DirectiveDescriptor {
|
||||
],
|
||||
|
||||
...((() => {
|
||||
const sentryFeature = config.features.sentry;
|
||||
if (!sentryFeature.isEnabled || !sentryFeature.cspReportUrl || config.app.isDev) {
|
||||
if (!config.features.sentry.isEnabled) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
'report-uri': [
|
||||
sentryFeature.cspReportUrl,
|
||||
],
|
||||
getCspReportUrl(),
|
||||
].filter(Boolean),
|
||||
};
|
||||
})()),
|
||||
};
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
"lint:eslint": "eslint . --ext .js,.jsx,.ts,.tsx",
|
||||
"lint:eslint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
|
||||
"lint:tsc": "tsc -p ./tsconfig.json",
|
||||
"lint:envs-validator:dev": "cd ./deploy/tools/envs-validator && ./dev.sh",
|
||||
"lint:envs-validator:test": "cd ./deploy/tools/envs-validator && ./test.sh",
|
||||
"prepare": "husky install",
|
||||
"format-svg": "svgo -r ./icons",
|
||||
"test:pw": "./tools/scripts/pw.sh",
|
||||
|
||||
Reference in New Issue
Block a user