ਐਸਾ ਕਨਫਿਗ ਪੈਟਰਨ ਜੋ URLs, ਕੁੰਜੀਆਂ ਅਤੇ ਫੀਚਰ ਫਲੈਗਾਂ ਨੂੰ ਕੋਡ ਤੋਂ ਬਾਹਰ ਰੱਖਦਾ ਹੈ — ਵੈੱਬ, ਬੈਕਐਂਡ ਅਤੇ ਮੋਬਾਈਲ ਲਈ dev, staging, ਅਤੇ prod ਵਿੱਚ।

ਹਾਰਡਕੋਡ ਕੀਤੀ ਕਨਫਿਗ ਪਹਿਲੇ ਦਿਨ ਠੀਕ ਲੱਗਦੀ ਹੈ। ਫਿਰ ਤੁਹਾਨੂੰ staging ਵਾਤਾਵਰਣ, ਦੂਜਾ API, ਜਾਂ ਇੱਕ ਛੋਟੀ ਫੀਚਰ ਸਵਿੱਚ ਦੀ ਲੋੜ ਪੈਂਦੀ ਹੈ, ਅਤੇ ਉਹ “ਸਰਲ” ਬਦਲਾਅ ਰਿਲੀਜ਼ ਰਿਸਕ ਬਣ ਜਾਂਦਾ ਹੈ। حل ਸਧਾਰਨ ਹੈ: ਇਨਵਾਇਰਨਮੈਂਟ ਮੁੱਲਾਂ ਨੂੰ ਸਰੋਤ ਫਾਇਲਾਂ ਤੋਂ ਬਾਹਰ ਰੱਖੋ ਅਤੇ ਇੱਕ ਪੂਰੀ ਤਰੀਕੇ ਨਾਲ ਅਨੁਮਾਨਯੋਗ ਸੈਟਅਪ ਵਿੱਚ ਦਿਓ।
ਆਮ ਤੌਰ 'ਤੇ ਸਮੱਸਿਆਉਂ ਦੇ ਕਾਰਨ ਆਸਾਨੀ ਨਾਲ ਨਜ਼ਰ ਆਉਂਦੇ ਹਨ:
“ਸਿਰਫ਼ prod ਲਈ ਬਦਲੋ” ਇੱਕ ਆਦਤ ਬਣਾਉਂਦਾ ਹੈ ਜੋ ਆਖ਼ਰੀ ਮਿੰਟ ਦੀਆਂ ਸੋਧਾਂ ਨੂੰ ਉਤਪੰਨ ਕਰਦੀ ਹੈ। ਉਹ ਸੋਧ ਅਕਸਰ ਰਿਵਿਊ, ਟੈਸਟ ਅਤੇ ਦੁਹਰਾਈ ਤੋਂ ਬਿਨਾਂ ਹੋ ਜਾਂਦੀਆਂ ਹਨ। ਇੱਕ ਲੋਕ URL ਬਦਲਦਾ ਹੈ, ਦੂਜਾ ਕੁੰਜੀ, ਅਤੇ ਹੁਣ ਤੁਹਾਨੂੰ ਇੱਕ ਆਮ ਸਵਾਲ ਦਾ ਜਵਾਬ ਨਹੀਂ ਮਿਲਦਾ: ਇਸ ਬਿਲਡ ਨਾਲ ਕਿਹੜੀ ਸਟਰੀਕਲ ਕਨਫਿਗ ਸ਼ਿਪ ਹੋਈ?
ਆਮ ਸਥਿਤੀ: ਤੁਸੀਂ ਇੱਕ ਨਵਾਂ ਮੋਬਾਈਲ ਵਰਜਨ staging ਦੇ ਖਿਲਾਫ਼ ਬਣਾਉਂਦੇ ਹੋ, ਫਿਰ ਕਿਸੇ ਨੇ ਰਿਲੀਜ਼ ਤੋਂ ਠਿੱਠੇ ਪਹਿਲਾਂ URL ਨੂੰ prod 'ਤੇ ਸਵਿੱਚ ਕਰ ਦਿੱਤਾ। ਅਗਲੇ ਦਿਨ ਬੈਕਐਂਡ ਫੇਰ ਬਦਲਦਾ ਹੈ, ਅਤੇ ਤੁਹਾਨੂੰ rollback ਕਰਨ ਦੀ ਲੋੜ ਪੈਂਦੀ ਹੈ। ਜੇ URL ਹਾਰਡਕੋਡ ਹੈ, ਤਾਂ rollback ਦਾ مطلب ਹੋਰ ਐਪ ਅੱਪਡੇਟ ਹੋਣਾ ਹੈ। ਯੂਜ਼ਰ ਉਡੀਕਦੇ ਹਨ, ਅਤੇ ਸਪੋਰਟ ਟਿਕਟ ਭਰ ਜਾਂਦੇ ਹਨ।
ਲਕਸ਼ਯ ਇੱਥੇ ਇੱਕ ਸਧਾਰਨ ਯੋਜਨਾ ਹੈ ਜੋ ਵੈੱਬ, Go ਬੈਕਐਂਡ ਅਤੇ Flutter ਮੋਬਾਈਲ ਐਪ ਤੇ ਚੰਗੀ ਤਰ੍ਹਾਂ ਕੰਮ ਕਰੇ:
Dev, staging, ਅਤੇ prod ਇਕੋ ਐਪ ਵਾਂਗ ਮਹਿਸੂਸ ਹੋਣੇ ਚਾਹੀਦੇ ਹਨ ਜੋ ਤਿੰਨ ਵੱਖਰੇ ਥਾਵਾਂ ਤੇ ਚਲ ਰਹੀ ਹੋਵੇ। ਮਕਸਦ ਮੁਲਾਂ ਨੂੰ ਬਦਲਣਾ ਹੈ, ਵਿਹੇਵਿਅਰ ਨੂੰ ਨਹੀਂ।
ਕੋਈ ਵੀ ਚੀਜ਼ ਜੋ ਐਪ ਦੇ ਚਲਣ ਜਾਂ ਕਿਸ ਨੇ ਇਸਨੂੰ ਵਰਤ ਰਿਹਾ ਹੈ ਨਾਲ ਜੁੜੀ ਹੋਵੇ ਉਹ ਬਦਲਣੀ ਚਾਹੀਦੀ ਹੈ: base URLs ਅਤੇ hostnames, ਕ੍ਰੈਡੈਂਸ਼ਲ, sandbox vs real integrations, ਅਤੇ ਸੁਰੱਖਿਆ ਕਨਟਰੋਲ ਜਿਵੇਂ logging level ਜਾਂ prod ਵਿੱਚ ਸਖਤ ਸੈਟਿੰਗਾਂ।
ਜੋ ਚੀਜ਼ ਇਕੋ ਰਹਿਣੀ ਚਾਹੀਦੀ ਹੈ, ਉਹ ਹੈ ਲੋਜਿਕ ਅਤੇ ਭਾਗਾਂ ਦਰਮਿਆਨ ਦਾ ਸਮਝੌਤਾ (contract). API ਰੂਟ, request/response ਆਕਾਰ, ਫੀਚਰ ਨਾਮ ਅਤੇ ਕੁਆਰ-ਬਿਜ਼ਨੈੱਸ ਨਿਯਮਾਂ ਨੂੰ ਵਾਤਾਵਰਣ ਮੁਤਾਬਕ ਨਹੀਂ ਬਦਲਣਾ ਚਾਹੀਦਾ। ਜੇ staging ਵੱਖਰਾ ਵਿਹੇਵਿਅਰ ਕਰਦਾ ਹੈ, ਤਾਂ ਉਹ production ਲਈ ਭਰੋਸੇਯੋਗ ਰਿਹਰਸਲ ਨਹੀਂ ਰਹਿੰਦਾ।
“ਨਵਾਂ environment” vs “ਨਵਾਂ config ਮੁੱਲ” ਲਈ ਪ੍ਰੈਕਟਿਕਲ ਨਿਯਮ: ਇੱਕ ਨਵਾਂ environment ਤਦੋਂ ਬਣਾਓ ਜਦੋਂ ਤੁਹਾਨੂੰ ਇਕ ਅਲੱਗ ਸਿਸਟਮ ਦੀ ਲੋੜ ਹੋਵੇ (ਅਲੱਗ ਡਾਟਾ, ਐਕਸੈਸ, ਅਤੇ ਜੋਖਮ)। ਜੇ ਸਿਰਫ਼ ਵੱਖਰੇ endpoints ਜਾਂ ਵੱਖਰੇ ਨੰਬਰਾਂ ਦੀ ਲੋੜ ਹੈ, ਤਾਂ ਇਕ config ਮੁੱਲ ਜੋੜੋ।
ਉਦਾਹਰਣ: ਤੁਸੀਂ ਨਵਾਂ search provider ਟੈਸਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ। ਜੇ ਇਹ ਛੋਟੀ ਗਰੁੱਪ ਲਈ ਸੈਫ਼ ਹੈ, ਤਾਂ ਇੱਕ staging ਰੱਖੋ ਅਤੇ ਫੀਚਰ ਫਲੈਗ ਜੋੜੋ। ਜੇ ਇਹ ਅਲੱਗ ਡੇਟਾਬੇਸ ਅਤੇ ਸਖਤ ਐਕਸੈਸ ਕੰਟਰੋਲ ਮੰਗਦਾ ਹੈ, ਤਾਂ ਨਵਾਂ environment ਸਮਝਦਾਰ ਹੈ।
ਹਰ ਚੀਜ਼ ਇਕ ਚੀਜ਼ ਚੰਗੀ ਤਰ੍ਹਾਂ ਕਰੇ: ਅਕਸਮਾਤਿਕ ਤਰੀਕੇ ਨਾਲ dev URL, ਟੈਸਟ ਕੀ, ਜਾਂ ਅਧੂਰਾ ਫੀਚਰ ship ਹੋਣ ਤੋਂ ਰੋਕੇ।
ਹਰ ਐਪ (web, backend, mobile) ਲਈ ਇਕੋ ਤਿੰਨ ਲੇਅਰ ਵਰਤੋ:
ਉਲਝਣ ਤੋਂ ਬਚਣ ਲਈ, ਹਰ ਐਪ ਲਈ ਇੱਕ ਸੱਚਾਈ ਦਾ ਸਰੋਤ ਚੁਣੋ ਅਤੇ ਉਸ ਤੇ ਟਿਕੋ। ਉਦਾਹਰਣ ਲਈ, ਬੈਕਐਂਡ startup ਤੇ environment variables ਤੋਂ ਪੜ੍ਹਦਾ ਹੈ, ਵੈਬ ਐਪ build-time variables ਜਾਂ ਇੱਕ ਛੋਟੀ runtime config file ਤੋਂ ਪੜ੍ਹਦੀ ਹੈ, ਅਤੇ ਮੋਬਾਈਲ ਐਪ build time 'ਤੇ ਚੁਣੇ ਹੋਏ environment file ਤੋਂ ਪੜ੍ਹਦੀ ਹੈ। ਹਰ ਐਪ ਦੇ ਅੰਦਰ ਇੱਕਸਰਤਾ ਕਿਸੇ ਕੁਝ ਹੋਰ ਤਰੀਕੇ ਨੂੰ ਮਜ਼ਬੂਰ ਕਰਨ ਨਾਲੋਂ ਮਹੱਤਵਪੂਰਨ ਹੈ।
ਇੱਕ ਸਧਾਰਨ, ਦੁਹਰਾਏ ਜਾਣਯੋਗ ਸਕੀਮ ਇੰਝ ਦਿਖਦੀ ਹੈ:
ਹਰ config ਆਈਟਮ ਨੂੰ ਅਜਿਹਾ ਨਾਮ ਦਿਓ ਜੋ ਤਿੰਨ ਸਵਾਲਾਂ ਦਾ ਜਵਾਬ ਦੇਵੇ: ਇਹ ਕੀ ਹੈ, ਕਿੱਥੇ ਲਾਗੂ ਹੁੰਦਾ ਹੈ, ਅਤੇ ਇਸ ਦੀ ਕਿਸ ਕਿਸਮ ਦੀ ਮੁੱਲ ਹੈ।
ਇੱਕ ਪ੍ਰਯੋਗਯੋਗ ਰਿਵਾਜ:
ਇਸ ਤਰ੍ਹਾਂ ਕਿਸੇ ਨੂੰ ਅਨੁਮਾਨ ਨਹੀਂ ਕਰਨਾ ਪਏਗਾ ਕਿ “BASE_URL” React ਲਈ ਹੈ, Go ਸਰਵਿਸ ਲਈ, ਜਾਂ Flutter ਲਈ।
React ਕੋਡ ਉਜ਼ਰ ਦੇ ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ ਚੱਲਦਾ ਹੈ, ਇਸ ਲਈ ਜੋ ਕੁਝ ਤੁਸੀਂ ship ਕਰਦੇ ਹੋ, ਉਹ ਪੜ੍ਹਿਆ ਜਾ ਸਕਦਾ ਹੈ। ਟੀਚਾ ਸਧਾਰਨ ਹੈ: ਸਰਵਰ 'ਤੇ ਸੀਕਰੇਟਸ ਰੱਖੋ, ਅਤੇ ਬ੍ਰਾਊਜ਼ਰ ਨੂੰ ਸਿਰਫ਼ ਸੁਰੱਖਿਅਤ ਸੈਟਿੰਗਾਂ ਜਿਵੇਂ API base URL, ਐਪ ਨਾਂ, ਜਾਂ ਗੈਰ-ਸੰਵੇਦਨਸ਼ੀਲ ਫੀਚਰ ਟੌਗਲ ਹੀ ਦੇਉ।
Build-time config ਉਸ ਵੇਲੇ inject ਹੁੰਦੀ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਬੰਡਲ ਨੂੰ ਬਣਾਉਂਦੇ ਹੋ। ਉਹ ਮੁੱਲ ਜੋ ਕਮ ਹੀ ਬਦਲਦੇ ਅਤੇ ਦਿਖਾਉਣ ਲਈ ਸੁਰੱਖਿਅਤ ਹਨ, ਲਈ ਠੀਕ ਹੈ।
Runtime config ਉਸ ਵੇਲੇ ਲੋਡ ਹੁੰਦੀ ਹੈ ਜਦੋਂ ਐਪ ਸ਼ੁਰੂ ਹੁੰਦਾ ਹੈ (ਉਦਾਹਰਣ ਲਈ, ਐਪ ਦੇ ਨਾਲ ਸਰਵ ਕੀਤੀ ਇੱਕ ਛੋਟੀ JSON ਫਾਇਲ ਜਾਂ injected global)। ਇਹ ਉਹ ਮੁੱਲਾਂ ਲਈ ਚੰਗੀ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ deploy ਤੋਂ ਬਾਅਦ ਤੁਸੀਂ ਬਦਲਣਾ ਚਾਹੁੰਦੇ ਹੋ, ਜਿਵੇਂ API base URL ਨੂੰ ਵਾਤਾਵਰਣਾਂ ਵਿਚ ਸਵਿੱਚ ਕਰਨਾ।
ਇਕ ਸਧਾਰਨ ਨਿਯਮ: ਜੇ ਇਸਨੂੰ ਬਦਲਣਾ UI ਨੂੰ ਮੁੜ ਬਣਾਉਣ ਦੀ ਲੋੜ ਨਹੀਂ ਰੱਖਣਾ ਚਾਹੀਦਾ, ਤਾਂ ਇਸਨੂੰ runtime ਬਣਾਓ।
ਡੈਵ ਲਈ ਇੱਕ ਲੋਕਲ ਫਾਇਲ ਰੱਖੋ (gitignored) ਅਤੇ ਬਿਲਡ/ਡਿਪਲੌਇ ਪਾਈਪਲਾਈਨ ਵਿੱਚ ਅਸਲੀ ਮੁੱਲ ਸੈਟ ਕਰੋ।
.env.local (gitignored) ਵਰਤੋ, ਉਦਾਹਰਣ: VITE_API_BASE_URL=http://localhost:8080VITE_API_BASE_URL ਨੂੰ environment variable ਵਜੋਂ ਸੈਟ ਕਰੋ, ਜਾਂ deploy ਦੌਰਾਨ ਬਣਾਈ ਗਈ runtime config file ਵਿੱਚ ਰੱਖੋRuntime ਉਦਾਹਰਣ (ਐਪ ਦੇ ਨਾਲ ਸਰਵ ਕੀਤੀ config):
{ "apiBaseUrl": "https://api.staging.example.com", "features": { "newCheckout": false } }
ਫਿਰ ਇਸਨੂੰ startup 'ਤੇ ਇੱਕ ਵਾਰੀ ਲੋਡ ਕਰੋ ਅਤੇ ਇਕ ਹੀ ਥਾਂ ਰੱਖੋ:
export async function loadConfig() {
const res = await fetch('/config.json', { cache: 'no-store' });
return res.json();
}
React env vars ਨੂੰ public ਮੰਨੋ। ਪਾਸਵਰਡ, ਨਿੱਜੀ API keys, ਜਾਂ ਡੇਟਾਬੇਸ URLs ਵੈਬ ਐਪ ਵਿੱਚ ਨਾ ਰੱਖੋ।
ਸੁਰੱਖਿਅਤ ਉਦਾਹਰਣ: API base URL, Sentry DSN (public), build version, ਅਤੇ ਸਧਾਰਨ ਫੀਚਰ ਫਲੈਗ।
ਬੈਕਐਂਡ ਕਨਫਿਗ ਜ਼ਿਆਦਾ ਸੁਰੱਖਿਅਤ ਰਹਿਣ ਲਈ typed, environment variables ਤੋਂ ਲੋਡ ਅਤੇ ਸਰਵਰ ਟਰੈਫਿਕ ਮਨਜ਼ੂਰ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ validate ਕੀਤੀ ਜਾਣੀ ਚਾਹੀਦੀ ਹੈ।
ਸਰੂਆਤ ਇਸ ਗੱਲ ਨਾਲ ਕਰੋ ਕਿ ਬੈਕਐਂਡ ਨੂੰ ਚਲਾਉਣ ਲਈ ਕਿਹੜੀਆਂ ਮੁੱਲਾਂ ਦੀ ਲੋੜ ਹੈ, ਅਤੇ ਉਹਨਾਂ 값을 ਖੁੱਲ੍ਹੇ ਤੌਰ ਤੇ ਰੱਖੋ। ਆਮ “ਹੁਣ ਚੱਲਣੇ” ਮੁੱਲ ਹਨ:
APP_ENV (dev, staging, prod)HTTP_ADDR (ਉਦਾਹਰਨ :8080)DATABASE_URL (Postgres DSN)PUBLIC_BASE_URL (callbacks ਅਤੇ links ਲਈ)API_KEY (ਤ੍ਰੀਜੇ-ਪੱਖੀ ਸੇਵਾ ਲਈ)ਫਿਰ ਉਹਨਾਂ ਨੂੰ struct ਵਿੱਚ ਲੋਡ ਕਰੋ ਅਤੇ ਜੇ ਕੁਝ ਗੁੰਮ ਹੈ ਜਾਂ ਗਲਤ ਹੈ ਤਾਂ ਤੁਰੰਤ ਫੇਲ ਕਰੋ। ਇਸ ਤਰ੍ਹਾਂ ਤੁਸੀਂ ਕੁਝ ਸਕਿੰਟਾਂ ਵਿੱਚ ਸਮੱਸਿਆ ਮਿਲ ਜਾਂਦੀ ਹੈ, ਨਾ ਕਿ ਅਧ ਪਹੁੰਚ ਵਾਲੇ deploy ਤੋਂ ਬਾਅਦ।
package config
import (
"errors"
"net/url"
"os"
"strings"
)
type Config struct {
Env string
HTTPAddr string
DatabaseURL string
PublicBaseURL string
APIKey string
}
func Load() (Config, error) {
c := Config{
Env: mustGet("APP_ENV"),
HTTPAddr: getDefault("HTTP_ADDR", ":8080"),
DatabaseURL: mustGet("DATABASE_URL"),
PublicBaseURL: mustGet("PUBLIC_BASE_URL"),
APIKey: mustGet("API_KEY"),
}
return c, c.Validate()
}
func (c Config) Validate() error {
if c.Env != "dev" && c.Env != "staging" && c.Env != "prod" {
return errors.New("APP_ENV must be dev, staging, or prod")
}
if _, err := url.ParseRequestURI(c.PublicBaseURL); err != nil {
return errors.New("PUBLIC_BASE_URL must be a valid URL")
}
if !strings.HasPrefix(c.DatabaseURL, "postgres://") {
return errors.New("DATABASE_URL must start with postgres://")
}
return nil
}
func mustGet(k string) string {
v, ok := os.LookupEnv(k)
if !ok || strings.TrimSpace(v) == "" {
panic("missing env var: " + k)
}
return v
}
func getDefault(k, def string) string {
if v, ok := os.LookupEnv(k); ok && strings.TrimSpace(v) != "" {
return v
}
return def
}
ਇਸ ਨਾਲ database DSNs, API keys, ਅਤੇ callback URLs ਕੋਡ ਅਤੇ git ਤੋਂ ਬਾਹਰ ਰਹਿੰਦੇ ਹਨ। ਹੋਸਟ ਕੀਤੀਆਂ ਸੈਟਿੰਗਾਂ ਵਿੱਚ, ਤੁਸੀਂ environmentਾਂ ਅਨੁਸਾਰ ਇਹ env vars inject ਕਰੋ ਤਾਂ ਕਿ dev, staging, ਅਤੇ prod ਇੱਕ-ਲਾਈਨ ਵੀ ਨਾ ਬਦਲਣ।
Flutter ਐਪ ਆਮ ਤੌਰ 'ਤੇ ਦੋ ਲੇਅਰਾਂ ਦੀ ਲੋੜ ਹੈ: build-time flavors (ਕਿਸ ਨੂੰ ਤੁਸੀਂ ship ਕਰਦੇ ਹੋ) ਅਤੇ runtime ਸੈਟਿੰਗਜ਼ (ਜਿਹਨੂੰ ਐਪ ਨਵੇਂ ਰਿਲੀਜ਼ ਬਿਨਾਂ ਬਦਲ ਸਕਦਾ ਹੈ)। ਇਹਨਾਂ ਨੂੰ ਵੱਖਰਾ ਰੱਖਣ ਨਾਲ “ਸਿਰਫ਼ ਇੱਕ ਛੋਟੀ URL ਬਦਲੀ” ਐਮਰਜੈਂਸੀ ਰੀਬਿਲਡ ਵਿੱਚ ਨਹੀਂ ਬਦਲਦੀ।
ਤਿੰਨ ਫਲੇਵਰਸ ਬਣਾਓ: dev, staging, prod. ਫਲੇਵਰਸ ਉਹ ਚੀਜ਼ਾਂ ਨਿਰਧਾਰਤ ਕਰਨ ਜੋ build time ਤੇ ਹੀ ਫਿਕਸ ਹੋਣੀਆਂ ਚਾਹੀਦੀਆਂ ਹਨ, ਜਿਵੇਂ app name, bundle id, signing, analytics project, ਅਤੇ debug tools ਕਿੱਥੇ enable ਹਨ।
ਫਿਰ --dart-define (ਜਾਂ ਤੁਹਾਡੇ CI) ਨਾਲ ਸਿਰਫ़ non-sensitive defaults ਪਾਸ ਕਰੋ ਤਾਂ ਕਿ ਕਦੇ ਵੀ ਉਹਨਾਂ ਨੂੰ ਕੋਡ ਵਿੱਚ ਹਾਰਡਕੋਡ ਨਾ ਕਰੋ:
ENV=stagingDEFAULT_API_BASE=https://api-staging.example.comCONFIG_URL=https://config.example.com/mobile.jsonDart ਵਿੱਚ String.fromEnvironment ਨਾਲ ਪੜ੍ਹੋ ਅਤੇ startup 'ਤੇ ਇੱਕ ਸਧਾਰਨ AppConfig ਔਬਜੈਕਟ ਬਣਾਓ।
ਜੇ ਤੁਸੀਂ ਛੋਟੀ endpoint ਬਦਲਾਂ ਲਈ ਰੀਬਿਲਡ ਤੋਂ ਬਚਣਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ API base URL ਨੂੰ constant ਨਾ ਮੰਨੋ। ਐਪ ਲਾਂਚ 'ਤੇ ਇੱਕ ਛੋਟਾ config file fetch ਕਰੋ (ਅਤੇ cache ਕਰੋ)। ਫਲੇਵਰ ਸਿਰਫ਼ ਇਸ ਗੱਲ ਨੂੰ ਨਿਰਧਾਰਤ ਕਰੇ ਕਿ config ਕਿੱਥੋਂ ਲੈਣਾ ਹੈ।
ਇੱਕ ਪ੍ਰਯੋਗਯੋਗ ਵੰਡ:
ਜੇ ਤੁਸੀਂ ਆਪਣਾ ਬੈਕਐਂਡ move ਕਰਦੇ ਹੋ, ਤਾਂ remote config ਨੂੰ update ਕਰੋ ਤਾਂ ਕਿ ਨਵਾਂ base URL ਦਰਸਾਇਆ ਜਾਵੇ। ਮੌਜੂਦਾ ਯੂਜ਼ਰ ਅਗਲੇ ਲਾਂਚ 'ਤੇ ਉਹ ਲੈਂਦੇ ਹਨ, ਅਤੇ ਪਿਛਲਾ cache fallback ਤੌਰ 'ਤੇ ਕੰਮ ਕਰਦਾ ਹੈ।
ਫੀਚਰ ਫਲੈਗ gradual rollouts, A/B ਟੈਸਟਾਂ, quick kill switches, ਅਤੇ staging ਵਿੱਚ ਖਤਰਨਾਕ ਬਦਲਾਂ ਨੂੰ ਟੈਸਟ ਕਰਨ ਲਈ ਮੁਫ਼ীদ ਹਨ। ਇਹ ਸੁਰੱਖਿਆ ਨਿਯਮਾਂ ਦੀ ਜਗ੍ਹਾ ਨਹੀਂ ਹੋ ਸਕਦੇ। ਜੇ ਕਿਸੇ ਚੀਜ਼ ਨੂੰ ਇੱਕ ਫਲੈਗ ਰੱਖਣ ਨਾਲ ਸੁਰੱਖਿਆ ਦੀ ਜ਼ਰੂਰਤ ਹੁੰਦੀ ਹੈ, ਤਾਂ ਉਹ ਫਲੈਗ ਨਹੀਂ — ਉਹ auth rule ਹੈ।
ਹਰ ਫਲੈਗ ਨੂੰ ਇੱਕ API ਵਾਂਗ ਸਲੂਕ ਕਰੋ: ਸਪਸ਼ਟ ਨਾਮ, ਇੱਕ ਮਾਲਕ, ਅਤੇ ਇੱਕ ਖਤਮ ਹੋਣ ਦੀ ਮਿਤੀ।
ਉਹ ਨਾਂ ਵਰਤੋ ਜੋ ਦੱਸਣ ਕਿ ਫਲੈਗ ON ਹੋਣ 'ਤੇ ਕੀ ਹੁੰਦਾ ਹੈ, ਅਤੇ ਪ੍ਰੋਡਕਟ ਦੇ ਕਿਸ ਹਿੱਸੇ ਨੂੰ ਛੂਹਦਾ ਹੈ। ਇੱਕ ਸਧਾਰਨ ਸਕੀਮ:
feature.checkout_new_ui_enabled (ਗਾਹਕ-ਮੁਖੀ ਫੀਚਰ)ops.payments_kill_switch (ਐਮਰਜੈਂਸੀ ਬੰਦ ਕਰਨ ਵਾਲਾ)exp.search_rerank_v2 (ਪ੍ਰਯੋਗ)release.api_v3_rollout_pct (ਧੀਰੇ ਧੀਰੇ ਰੋਲਆਉਟ)debug.show_network_logs (ਡਾਇਗਨੋਸਟਿਕ)ਪੌਜ਼ੇਟਿਵ boolean (..._enabled) ਨੂੰ ਪਸੰਦ ਕਰੋ। ਇੱਕ ਸਥਿਰ ਪ੍ਰੀਫਿਕਸ ਰੱਖੋ ਤਾਂ ਜੋ ਤੁਸੀਂ ਫਲੈਗ ਨੂੰ ਖੋਜ ਅਤੇ ਆਡਿਟ ਕਰ ਸਕੋ।
ਸੁਰੱਖਿਅਤ ਡਿਫਾਲਟਸ ਨਾਲ ਸ਼ੁਰੂ ਕਰੋ: ਜੇ ਫਲੈਗ ਸਰਵਿਸ ਡਾਊਨ ਹੈ, ਤਾਂ ਤੁਹਾਡੀ ਐਪ ਸਥਿਰ ਵਰਜ਼ਨ ਵਾਂਗ ਸੇਵ ਕਰੇ।
ਇੱਕ ਹਕੀਕਤੀ ਪੈਟਰਨ: ਬੈਕਐਂਡ ਵਿੱਚ ਨਵਾਂ endpoint ship ਕਰੋ, ਪੁਰਾਣਾ ਇੱਕੋ ਢੰਗ ਨਾਲ ਚਲਾਉ ਰੱਖੋ, ਅਤੇ release.api_v3_rollout_pct ਨਾਲ ਟ੍ਰੈਫਿਕ ਧੀਰੇ-ਧੀਰੇ ਸਵਿੱਚ ਕਰੋ। ਜੇ ਐਰਰ ਵੱਧੇ, ਤਾਂ ਬਿਨਾਂ ਹੌਟਫਿਕਸ ਦੇ ਇਹ ਵਾਪਸ ਪਲਿੱਪ ਕਰੋ।
ਫਲੈਗ ਸਟੈਕ ਨੂੰ ਰੋਕਣ ਲਈ ਕੁਝ ਨਿਯਮ ਰੱਖੋ:
“ਸੀਕਰੇਟ” ਉਹ ਹੈ ਜਿਸ ਦਾ ਲੀਕ ਹੋਣਾ ਨੁਕਸান ਦਾ ਕਾਰਨ ਬਣੇ। ਸੋਚੋ API tokens, database passwords, OAuth client secrets, signing keys (JWT), webhook secrets, ਅਤੇ ਨਿੱਜੀ ਸਰਟੀਫਿਕੇਟ। ਸੀਕਰੇਟ ਨਹੀਂ: API base URLs, build numbers, feature flags, ਜਾਂ public analytics IDs।
ਸੀਕਰੇਟਸ ਨੂੰ ਬਾਕੀ ਸੈਟਿੰਗਜ਼ ਤੋਂ ਵੱਖਰਾ ਰੱਖੋ। ਡਿਵੈਲਪਰ ਸੁਰੱਖਿਅਤ ਕਨਫਿਗ ਨੂੰ ਆਜ਼ਾਦੀ ਨਾਲ ਬਦਲ ਸਕਣ, ਜਦਕਿ ਸੀਕਰੇਟਸ ਸਿਰਫ runtime 'ਤੇ inject ਹੋਣ ਤੇ ਜਿੱਥੇ ਲੋੜ ਹੋਵੇ ਉੱਥੇ ਹੀ ਰਹਿਣ।
Dev ਵਿੱਚ ਸੀਕਰੇਟਸ ਲੋਕਲ ਅਤੇ disposable ਰੱਖੋ। .env ਫਾਇਲ ਜਾਂ OS keychain ਵਰਤੋ ਅਤੇ ਇਸਨੂੰ ਰੀਸੈੱਟ ਕਰਨਾ ਆਸਾਨ ਰੱਖੋ। ਕਦੇ commit ਨਾ ਕਰੋ।
Staging ਅਤੇ Prod ਵਿੱਚ, ਸੀਕਰੇਟਸ ਇੱਕ ਸਮਰਪਿਤ secrets store ਵਿੱਚ ਰਹਿਣੇ ਚਾਹੀਦੇ ਹਨ, ਨਾ ਕਿ ਕੋਡ ਰੀਪੋ, ਚੈਟ ਲੌਗ, ਜਾਂ ਮੋਬਾਈਲ ਐਪ ਵਿੱਚ bake ਹੋਏ।
ਰੋਟੇਸ਼ਨ ਅਸਫਲ ਹੁੰਦੀ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਕੀ swap ਕਰਦੇ ਹੋ ਅਤੇ ਭੁੱਲ ਜਾਂਦੇ ਹੋ ਕਿ ਪੁਰਾਣੇ clients ਨੂੰ ਵੀ ਇਹ ਵਰਤਣ ਦੀ ਲੋੜ ਹੈ। ਇੱਕ overlap window ਦੀ ਯੋਜਨਾ ਬਣਾਓ।
ਇਹ overlap ਦ੍ਰਿਸ਼ਟੀਕੋਣ API keys, webhook secrets, ਅਤੇ signing keys ਲਈ ਕੰਮ ਕਰਦਾ ਹੈ ਅਤੇ ਅਚਾਨਕ outage ਤੋਂ ਬਚਾਉਂਦਾ ਹੈ।
ਤੁਹਾਡੇ ਕੋਲ ਇੱਕ staging API ਹੈ ਅਤੇ ਨਵਾਂ production API। ਟਰਫਿਕ ਨੂੰ ਫੇਜ਼ਾਂ ਵਿੱਚ ਸਵਿੱਚ ਕਰਨ ਦਾ ਟੀਚਾ ਹੈ, ਅਤੇ ਤੇਜ਼ੀ ਨਾਲ ਵਾਪਸ ਆਉਣ ਦਾ ਰਸਤਾ ਰੱਖਣਾ। ਇਹ ਤਾਂ ਹੀ ਅਸਾਨ ਹੁੰਦਾ ਹੈ ਜਦੋਂ ਐਪ API base URL ਨੂੰ config ਤੋਂ ਪੜ੍ਹਦਾ ਹੋਵੇ, ਨਾ ਕਿ ਕੋਡ ਵਿੱਚ embed ਕੀਤਾ ਹੋਵੇ।
ਹਰ ਜਗ੍ਹਾ API URL ਨੂੰ deploy-time ਮੁੱਲ ਤਰ੍ਹਾਂ ਵਤੋਂ ਹੰਢਾਇਆ ਜਾਵੇ। ਵੈਬ (React) ਵਿੱਚ ਇਹ ਆਮ ਤੌਰ ਤੇ build-time ਮੁੱਲ ਜਾਂ runtime config file ਹੁੰਦੀ ਹੈ। ਮੋਬਾਈਲ (Flutter) ਵਿੱਚ ਆਮ ਤੌਰ ਤੇ flavor + remote config। ਬੈਕਐਂਡ (Go) ਵਿੱਚ runtime env var। ਅਹੰਕਾਰਕ ਹਿੱਸਾ ਹੇਠਾਂ ਹੈ: ਕੋਡ ਇੱਕ ਹੀ ਵੈਰੀਏਬਲ ਨਾਮ (ਉਦਾਹਰਨ ਲਈ API_BASE_URL) ਵਰਤੇ ਅਤੇ ਕਦੇ ਵੀ URL ਨੂੰ components/services/screens ਵਿੱਚ embed ਨਾ ਕਰੋ।
ਇੱਕ ਸੁਰੱਖਿਅਤ ਫੇਜ਼ਡ ਰੋਲਆਉਟ ਇੰਝ ਹੋ ਸਕਦਾ ਹੈ:
ਵੈਰੀਫਿਕੇਸ਼ਨ ਮੁੱਖ ਤੌਰ 'ਤੇ mismatches ਨੂੰ ਸ਼ੁਰੂ ਵਿੱਚ ਪਕੜਨ ਬਾਰੇ ਹੈ। ਅਸਲੀ ਯੂਜ਼ਰਾਂ ਦੇ ਹੱਕ ਵਿਚ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ, health endpoints ਨੂੰ ਚੈੱਕ ਕਰੋ, auth flows ਕੰਮ ਕਰਦੇ ਹਨ, ਅਤੇ ਇੱਕ same test account ਇੱਕ ਕ ключ ਯਾਤਰਾ end-to-end ਪੂਰੀ ਕਰ ਸਕਦਾ ਹੈ।
ਜ਼ਿਆਦਾਤਰ ਪ੍ਰੋਡਕਸ਼ਨ ਕਨਫਿਗ ਬੱਗ ਨਿੱਤੀਆਂ ਹਨ: ਇੱਕ staging ਮੁੱਲ ਰਹਿ ਗਿਆ, ਫਲੈਗ ਡਿਫਾਲਟ ਉਲਟ ਗਿਆ, ਜਾਂ ਇੱਕ API key ਕਿਸੇ ਖੇਤਰ ਵਿੱਚ ਗੁੰਮ। ਇੱਕ ਛੋਟੀ ਪਾਸ ਬਹੁਤ ਸਾਰੀਆਂ ਮੁਸਲਿਆਂ ਨੂੰ ਫੜ ਲੈਂਦੀ ਹੈ।
ਡਿਪਲੌਇ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ, ਇਹ ਤੀਨ ਚੀਜ਼ਾਂ ਟਾਰਗਟ ਇਨਵਾਇਰਨਮੈਂਟ ਨਾਲ ਮੇਲ ਖਾਂਦੀਆਂ ਹਨ: endpoints, secrets, ਅਤੇ defaults.
ਫਿਰ ਇੱਕ ਤੇਜ਼ smoke test ਕਰੋ। ਇੱਕ ਅਸਲੀ ਯੂਜ਼ਰ ਫਲੋ ਚੁਣੋ ਅਤੇ end-to-end ਚਲਾਓ, ਨਵਾਂ ਇੰਸਟਾਲ ਜਾਂ ਸਾਫ਼ ਬ੍ਰਾਊਜ਼ਰ ਪ੍ਰੋਫ਼ਾਈਲ ਵਰਤ ਕੇ ਤਾਂ ਜੋ cached tokens 'ਤੇ ਨਿਰਭਰ ਨਾ ਕਰੋ।
ਪ੍ਰੈਕਟਿਕਲ ਆਦਤ: staging ਨੂੰ production ਵਾਂਗ ਸਮਝੋ ਪਰ ਵੱਖਰੇ ਮੁੱਲਾਂ ਨਾਲ। ਇਸਦਾ ਮਤਲਬ ਇਕੋ config schema, ਇਕੋ validation ਨਿਯਮ, ਅਤੇ ਇਕੋ deployment ਆਕਾਰ। ਕੇਵਲ ਮੁੱਲ ਵੱਖਰੇ ਹੋਣੇ ਚਾਹੀਦੇ ਹਨ, ਸੰਰਚਨਾ ਨਹੀਂ।
ਜ਼ਿਆਦਾਤਰ configuration outages ਵਿਸ਼ਾਲ ਜਾਂ ਅਜੀਬ ਨਹੀਂ ਹੁੰਦੀਆਂ। ਉਹ ਸਧਾਰਨ ਗਲਤੀਆਂ ਹਨ ਜੋ ਫਾਇਲਾਂ, build steps, ਅਤੇ ਡੈਸ਼ਬੋਰਡਾਂ ਵਿੱਚ ਫੈਲਣ ਕਾਰਨ slip ਹੋ ਜਾਂਦੀਆਂ ਹਨ, ਅਤੇ ਕੋਈ ਇਹ ਨਹੀਂ ਪੁੱਛ ਸਕਦਾ: "ਹੁਣ ਇਹ ਐਪ ਕਿਹੜੀਆਂ ਮੁੱਲਾਂ ਵਰਤੇਗੀ?" ਇੱਕ ਚੰਗੀ ਸੈਟਅਪ ਇਸ ਸਵਾਲ ਨੂੰ ਆਸਾਨ ਬਣਾਉਂਦੀ ਹੈ।
ਚਾਹ: runtime ਮੁੱਲਾਂ ਨੂੰ build-time ਥਾਂਵਾਂ ਤੇ ਰੱਖਣਾ। React build ਵਿੱਚ API base URL bake ਕਰਨ ਦਾ ਨਤੀਜਾ ਇਹ ਹੁੰਦਾ ਹੈ ਕਿ ਤੁਹਾਨੂੰ ਹਰ environment ਲਈ rebuild ਕਰਨਾ ਪੈਂਦਾ ਹੈ। ਫਿਰ ਕੋਈ ਗਲਤ artifact deploy ਕਰ ਦਿੰਦਾ ਹੈ ਅਤੇ production staging ਨੂੰ ਪਵਦਾ ਹੈ।
ਇੱਕ ਸੁਰੱਖਿਅਤ ਨਿਯਮ: ਉਹੀ ਚੀਜ਼ਾਂ bake ਕਰੋ ਜੋ ਰੀਲਜ਼ ਤੋਂ ਬਾਅਦ ਕਦੇ ਨਹੀਂ ਬਦਲਣੀਆਂ (ਜਿਵੇਂ ਐਪ ਵਰਜ਼ਨ)। environment ਵੇਰਵੇ (API URLs, feature switches, analytics endpoints) ਜਿੱਥੇ ਸੰਭਵ ਹੋ runtime ਰੱਖੋ, ਅਤੇ ਸੱਚਾਈ ਦਾ ਸਰੋਤ obvious ਬਣਾਓ।
ਇਹ ਇਸ ਕਾਰਨ ਹੁੰਦਾ ਹੈ ਕਿ ਡਿਫਾਲਟਸ “ਮਦਦਗਾਰ” ਪਰ ਅਸੁਰੱਖਿਅਤ ਹੁੰਦੇ ਹਨ। ਇੱਕ ਮੋਬਾਈਲ ਐਪ ਜੇ config ਨਹੀਂ ਪੜ੍ਹ ਸਕਦਾ ਤਾਂ dev API ਨੂੰ ਡਿਫਾਲਟ ਕਰ ਸਕਦਾ ਹੈ, ਜਾਂ ਇੱਕ ਬੈਕਐਂਡ env var ਗੁੰਮ ਹੋਣ 'ਤੇ local database fallback ਕਰ ਸਕਦਾ ਹੈ। ਇਹ ਛੋਟੀ ਗਲਤੀ ਨੂੰ ਪੂਰੇ outage ਵਿੱਚ ਬਦਲ ਦਿੰਦਾ ਹੈ।
ਦੋ ਆਦਤਾਂ ਮਦਦਗਾਰ ਸਾਬਤ ਹੁੰਦੀਆਂ ਹਨ:
ਇੱਕ ਹਕੀਕਤੀ ਉਦਾਹਰਣ: ਇਕ ਰਿਲੀਜ਼ ਸ਼ੁੱਕਰਵਾਰ ਰਾਤ ਨੂੰ ਜਾਂਦੀ ਹੈ, ਅਤੇ ਪ੍ਰੋਡਕਸ਼ਨ build ਅਕਸਮਾਤ staging payment key ਰੱਖਦਾ ਹੈ। ਸਭ ਕੁਝ "ਚੱਲਦਾ" ਹੈ ਜਦ ਤੱਕ charges ਖ਼ਰਾਬ ਨਹੀਂ ਹੁੰਦੇ। ਦਰੁਸਤ ਕਰਨ ਲਈ ਨਵਾਂ payment library ਨਹੀਂ ਚਾਹੀਦਾ; ਇਹ validation ਦੀ ਲੋੜ ਹੈ ਜੋ production ਵਿੱਚ non-production keys reject ਕਰੇ।
ਜੇ staging production ਨਾਲ ਮਿਲਦਾ-ਜੁਲਦਾ ਨਹੀਂ ਰਹਿੰਦਾ, ਤਾਂ ਇਹ ਭਰੋਸੇਯੋਗ ਤੌਰ 'ਤੇ ਫੇਲ ਹੋ ਜਾਂਦਾ ਹੈ। ਵੱਖਰੇ ਡੇਟਾਬੇਸ ਸੈਟਿੰਗ, ਗੁੰਮ ਬੈਕਗ੍ਰਾਊਂਡ ਜੌਬਜ਼, ਜਾਂ ਵਾਧੂ ਫੀਚਰ ਫਲੈਗ ਬੱਗਸ ਨੂੰ ਸਿਰਫ਼ ਰਿਲੀਜ਼ ਤੋਂ ਬਾਅਦ ਹੀ ਦਰਸਾਉਂਦੇ ਹਨ।
Staging ਨੂੰ ਨੇੜੇ ਰੱਖੋ: ਇਕੋ config schema, ਇਕੋ validation ਨਿਯਮ, ਅਤੇ ਇਕੋ deployment ਆਕਾਰ ਨਕਲ ਕਰੋ। ਕੇਵਲ ਮੁੱਲਾਂ ਨੂੰ ਹੀ ਵੱਖਰਾ ਰੱਖੋ, ਨਾ ਢਾਂਚਾ।
ਮਕਸਦ ਕੋਈ fancy tooling ਨਹੀਂ ਹੈ। ਇਹ ਨਿਰਸ ਇਕਸਰਤਾ ਹੈ: ਇਕੋ ਨਾਮ, ਇਕੋ ਕਿਸਮ, ਇਕੋ ਨਿਯਮ dev, staging, ਅਤੇ prod ਵਿੱਚ। ਜਦੋਂ ਕਨਫਿਗ predictable ਹੁੰਦੀ ਹੈ, ਰਿਲੀਜ਼ ਦਖ਼ਲਅੰਦਾਜ਼ੀ ਘਟ ਜਾਂਦੀ ਹੈ।
ਇੱਕ ਥਾਂ 'ਤੇ ਇੱਕ ਸਪష్ట config contract ਲਿਖ ਕੇ ਸ਼ੁਰੂ ਕਰੋ। ਇਸਨੂੰ ਛੋਟਾ ਪਰ ਵਿਸ਼ੇਸ਼ ਰੱਖੋ: ਹਰ key ਨਾਮ, ਇਸ ਦੀ ਕਿਸਮ (string, number, boolean), ਕਿੱਥੋਂ ਆ ਸਕਦਾ ਹੈ (env var, remote config, build-time), ਅਤੇ ਇਸ ਦੀ ਡਿਫਾਲਟ। ਉਹਨਾਂ ਲਈ ਨੋਟਸ ਜੋ ਕਦੇ client app ਵਿੱਚ ਨਹੀਂ ਹੋਣੇ (ਜਿਵੇਂ private API keys)। ਇਸ contract ਨੂੰ ਇੱਕ API ਵਾਂਗ ਵਿਅਵਹਾਰ ਕਰੋ: ਬਦਲਾਅ ਨੂੰ ਰਿਵਿਊ ਦੀ ਲੋੜ ਹੋਵੇ।
ਫਿਰ ਗਲਤੀਆਂ early fail ਕਰਾਓ। CI ਵਿੱਚ ਗੁੰਮ API base URL ਖੋਜਨਾ deployment ਤੋਂ ਬਾਅਦ ਮਿਲਣ ਤੋਂ ਬਿਹਤਰ ਹੈ। Automated validation ਜੋ ਤੁਹਾਡੀ ਐਪ ਵਾਂਗ ਹੀ config ਲੋਡ ਕਰਦੀ ਹੈ ਅਤੇ ਚੈੱਕ ਕਰਦੀ ਹੈ:
ਅਖ਼ਿਰਕਾਰ, ਜਦੋਂ ਇੱਕ ਕਨਫਿਗ ਬਦਲ ਗਲਤ ਹੋਵੇ ਤਾਂ ਰਿਕਵਰ ਕਰਨਾ ਆਸਾਨ ਬਣਾਓ। ਜੋ ਚੱਲ ਰਿਹਾ ਹੈ ਉਸ ਦਾ snapshot ਲਓ, ਇੱਕ ਵਾਰੀ 'ਚ ਇੱਕ ਚੀਜ਼ ਬਦਲੋ, ਤੇਜ਼ੀ ਨਾਲ ਵੈਰੀਫਾਈ ਕਰੋ, ਅਤੇ ਰੋਲਬੈਕ ਪਾਥ ਰੱਖੋ।
ਜੇ ਤੁਸੀਂ Koder.ai (koder.ai) ਵਰਗੇ ਪਲੇਟਫਾਰਮ ਨਾਲ build ਅਤੇ deploy ਕਰ ਰਹੇ ਹੋ, ਉਹੀ ਨਿਯਮ ਲਾਗੂ ਹੁੰਦੇ ਹਨ: environment ਮੁੱਲਾਂ ਨੂੰ build ਅਤੇ hosting ਲਈ ਇਨਪੁਟ ਸਮਝੋ, secrets exported source ਵਿੱਚ ਨਾ ਰੱਖੋ, ਅਤੇ ship ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ config validate ਕਰੋ। ਇਹ ਇਕਸਰਤਾ ਹੀ redeploys ਅਤੇ rollbacks ਨੁਭਾਉਂਦੀ ਰੁਟੀਨ ਬਣਾਉਂਦੀ ਹੈ।
ਜਦੋਂ ਕਨਫਿਗ ਦਸਤਾਵੇਜ਼ਬੱਧ, validate ਅਤੇ reversible ਹੁੰਦੀ ਹੈ, ਤਾਂ ਇਹ outages ਦਾ ਸਰੋਤ ਬਣਨਾ ਬੰਦ ਕਰ ਦਿੰਦੀ ਅਤੇ shipping ਦਾ ਸਧਾਰਨ ਹਿੱਸਾ ਬਣ ਜਾਂਦੀ ਹੈ।