Commit 4b42b71e authored by tom goriunov's avatar tom goriunov Committed by GitHub

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
parent 0af703d5
......@@ -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
\ No newline at end of file
FAVICON_GENERATOR_API_KEY=xxx
\ No newline at end of file
......@@ -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,
......
#!/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
\ No newline at end of file
......@@ -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(),
......
#!/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}
yarn build
# Copy test assets
mkdir -p "./public/assets"
cp -r ${test_folder}/assets ./public/
PRESETS=(
"main"
"main.L2"
)
# Build validator script
yarn build
validate_preset() {
local preset="$1"
secrets_file="../../../configs/envs/.env.secrets"
config_file="../../../configs/envs/.env.${preset}"
validate_file() {
local test_file="$1"
echo
echo "------------------------------------------------"
echo "🧿 Validating preset '$preset'..."
echo "🧿 Validating file '$test_file'..."
dotenv \
-e $config_file \
-- bash -c '../../scripts/download_assets.sh ./public/assets'
dotenv \
-e $config_file \
-e $test_file \
-e $common_file \
-e $secrets_file \
yarn validate
yarn run validate -- --silent
if [ $? -eq 0 ]; then
echo "✅ Preset '$preset' is valid."
echo "------------------------------------------------"
echo
echo "👍 All good!"
return 0
else
echo "🛑 Preset '$preset' is invalid. Please fix it and run script again."
echo "------------------------------------------------"
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 preset in "${PRESETS[@]}"; do
validate_preset "$preset"
for file in "${test_files[@]}"; do
validate_file "$file"
if [ $? -eq 1 ]; then
exit 1
fi
......
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'}
\ No newline at end of file
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']
\ No newline at end of file
NEXT_PUBLIC_HAS_BEACON_CHAIN=true
NEXT_PUBLIC_BEACON_CHAIN_CURRENCY_SYMBOL=aETH
\ No newline at end of file
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
NEXT_PUBLIC_IS_L2_NETWORK=true
NEXT_PUBLIC_L1_BASE_URL=https://example.com
NEXT_PUBLIC_L2_WITHDRAWAL_URL=https://example.com
\ No newline at end of file
[
{
"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"
}
]
\ No newline at end of file
[
{
"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"
}
]
}
]
\ No newline at end of file
[
{
"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
&nbsp;
......
......@@ -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` |
&nbsp;
......
......@@ -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),
};
})()),
};
......
......@@ -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",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment