ضبط البيئة


ستحتاج في أغلب الأحيان إلى إعدادات إضافية لدوالّك، مثل مفاتيح واجهة برمجة التطبيقات التابعة لجهات خارجية أو إعدادات قابلة للضبط. توفّر حزمة Firebase SDK لنظام التشغيل Cloud Functions إعدادات بيئة مدمجة لتسهيل تخزين هذا النوع من البيانات واستردادها لمشروعك.

يمكنك الاختيار من بين هذه الخيارات:

  • الإعدادات المُعرَّفة بالمَعلمات (يُنصح بها في معظم السيناريوهات) يقدّم ذلك إعدادات بيئة بأنواع محدّدة باستخدام مَعلمات يتم التحقّق منها في وقت النشر، ما يؤدي بدوره إلى منع حدوث أخطاء وتبسيط عملية تصحيح الأخطاء.
  • الضبط المستنِد إلى الملفات لمتغيّرات البيئة باستخدام هذا النهج، يمكنك إنشاء ملف dotenv يدويًا لتحميل متغيّرات البيئة.

في معظم حالات الاستخدام، يُنصح باستخدام الإعدادات المُستندة إلى المَعلمات. يجعل هذا الأسلوب قيم التهيئة متاحة في وقت التشغيل ووقت النشر، ويتم حظر النشر ما لم يكن لجميع المعلمات قيمة صالحة. في المقابل، لا تتوفّر الإعدادات باستخدام متغيّرات البيئة في وقت النشر.

الإعدادات المُعلَمة

يوفّر Cloud Functions for Firebase واجهة لتحديد مَعلمات الإعدادات بشكل صريح داخل قاعدة بياناتك البرمجية. تتوفر قيمة هذه المعلمات أثناء نشر الدوال، وعند إعداد خيارات النشر ووقت التشغيل، وأثناء التنفيذ. وهذا يعني أنّ وحدة تحكّم سطر الأوامر ستحظر عملية النشر ما لم تكن جميع المَعلمات لها قيمة صالحة.

Node.js

const { onRequest } = require('firebase-functions/v2/https');
const { defineInt, defineString } = require('firebase-functions/params');

// Define some parameters
const minInstancesConfig = defineInt('HELLO_WORLD_MININSTANCES');
const welcomeMessage = defineString('WELCOME_MESSAGE');

// To use configured parameters inside the config for a function, provide them
// directly. To use them at runtime, call .value() on them.
export const helloWorld = onRequest(
  { minInstances: minInstancesConfig },
(req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam, StringParam

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")
WELCOME_MESSAGE = StringParam("WELCOME_MESSAGE")

# To use configured parameters inside the config for a function, provide them
# directly. To use them at runtime, call .value() on them.
@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
    return https_fn.Response(f'{WELCOME_MESSAGE.value()}! I am a function!')

عند نشر دالة باستخدام متغيّرات إعدادات مستندة إلى مَعلمات، يحاول ملف IDE لـ Firebase أولاً تحميل قيمها من ملفات ‎.env المحلية. إذا كانت هذه القيم غير متوفّرة في هذه الملفات ولم يتم ضبط default، سيطلب منك سطر الأوامر CLI تحديد القيم أثناء عملية النشر، ثم يحفظ قيمها تلقائيًا فيملف .env باسم .env.<project_ID> في دليل functions/:

$ firebase deploy
i  functions: preparing codebase default for deployment
? Enter a string value for ENVIRONMENT: prod
i  functions: Writing new parameter values to disk: .env.projectId
…
$ firebase deploy
i  functions: Loaded environment variables from .env.projectId

استنادًا إلى سير عمل التطوير، قد يكون من المفيد إضافة ملف .env.<project_ID> الذي تم إنشاؤه إلى نظام التحكّم في الإصدارات.

استخدام مَعلمات في نطاق عمومي

أثناء النشر، يتم تحميل رمز الدوال وفحصه قبل أن تحتوي المَعلمات على قيم فعلية. وهذا يعني أنّ جلب قيم المَعلمات أثناء النطاق العام يؤدي إلى تعذُّر النشر. في الحالات التي تريد فيها استخدام مَعلمة لإعداد قيمة عالمية، استخدِم دالة الاستدعاء لإعداد القيمة onInit(). يتم تشغيل عملية الاسترداد هذه قبل أي دوال في مرحلة الإنتاج، ولكن لا يتم استدعاؤها أثناء وقت النشر، لذا فهي مكان آمن للوصول إلى قيمة المعلمة.

Node.js

const { GoogleGenerativeAI } = require('@google/generative-ai');
const { defineSecret } = require('firebase-functions/params');
const { onInit } = require('firebase-functions/v2/core');

const apiKey = defineSecret('GOOGLE_API_KEY');

let genAI;
onInit(() => {
  genAI = new GoogleGenerativeAI(apiKey.value());
})

Python

from firebase_functions.core import init
from firebase_functions.params import StringParam, PROJECT_ID
import firebase_admin
import vertexai

location = StringParam("LOCATION")

x = "hello"

@init
def initialize():
  # Note: to write back to a global, you'll need to use the "global" keyword
  # to avoid creating a new local with the same name.
  global x
  x = "world"
  firebase_admin.initialize_app()
  vertexai.init(PROJECT_ID.value, location.value)

إذا كنت تستخدم معلَمات من النوع Secret، يُرجى العلم أنّها لا تتوفّر إلا في عملية الدوال التي ربطت المفتاح السرّي بها. في حال ربط مفتاح سرّي في بعض الدوال فقط، تحقَّق مما إذا كان secret.value() خادعًا قبل استخدامه.

ضبط سلوك واجهة سطر الأوامر

يمكن ضبط المَعلمات باستخدام كائن Options الذي يتحكّم في طريقة طلب واجهة سطر الأوامر للقيم. يحدِّد المثال التالي خيارات للتحقّق من تنسيق رقم الهاتف، وتوفير خيار اختيار بسيط، و preenchimento خيار اختيار تلقائيًا من مشروع Firebase:

Node.js

const { defineString } = require('firebase-functions/params');

const welcomeMessage = defineString('WELCOME_MESSAGE', {default: 'Hello World',
description: 'The greeting that is returned to the caller of this function'});

const onlyPhoneNumbers = defineString('PHONE_NUMBER', {
  input: {
    text: {
      validationRegex: /\d{3}-\d{3}-\d{4}/,
      validationErrorMessage: "Please enter
a phone number in the format XXX-YYY-ZZZZ"
    },
  },
});

const selectedOption = defineString('PARITY', {input: params.select(["odd", "even"])});

const memory = defineInt("MEMORY", {
  description: "How much memory do you need?",
  input: params.select({ "micro": 256, "chonky": 2048 }),
});

const extensions = defineList("EXTENSIONS", {
  description: "Which file types should be processed?",
  input: params.multiSelect(["jpg", "tiff", "png", "webp"]),
});

const storageBucket = defineString('BUCKET', {
  description: "This will automatically
populate the selector field with the deploying Cloud Project’s
storage buckets",
  input: params.PICK_STORAGE_BUCKET,
});

Python

from firebase_functions.params import (
    StringParam,
    ListParam,
    TextInput,
    SelectInput,
    SelectOptions,
    ResourceInput,
    ResourceType,
)

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")

WELCOME_MESSAGE = StringParam(
    "WELCOME_MESSAGE",
    default="Hello World",
    description="The greeting that is returned to the caller of this function",
)

ONLY_PHONE_NUMBERS = StringParam(
    "PHONE_NUMBER",
    input=TextInput(
        validation_regex="\d{3}-\d{3}-\d{4}",
        validation_error_message="Please enter a phone number in the format XXX-YYY-XXX",
    ),
)

SELECT_OPTION = StringParam(
    "PARITY",
    input=SelectInput([SelectOptions(value="odd"), SelectOptions(value="even")]),
)

STORAGE_BUCKET = StringParam(
    "BUCKET",
    input=ResourceInput(type=ResourceType.STORAGE_BUCKET),
    description="This will automatically populate the selector field with the deploying Cloud Project's storage buckets",
)

أنواع المَعلمات

توفّر الإعدادات المُعرَّفة بالمَعلمات كتابة قوية لقيم المَعلمات، ويسمح أيضًا بالسرّية من "أداة إدارة الأسرار في السحابة الإلكترونية". الأنواع المتوافقة هي:

  • سري
  • سلسلة
  • منطقي
  • العدد الصحيح
  • عائم
  • القائمة (Node.js)

تعابير المَعلمات وقيمها

يقيّم Firebase معلماتك في وقت النشر وأثناء تنفيذ الدالة. وبسبب هذه البيئتين المزدوجتين، يجب توخي الحذر عند مقارنة قيم المَعلمات وعند استخدامها لضبط خيارات بيئة التشغيل للدوال.

لتمرير معلمة إلى الدالة كخيار وقت تشغيل، عليك تمريرها مباشرةً:

Node.js

const { onRequest } = require('firebase-functions/v2/https');
const { defineInt } = require('firebase-functions/params');
const minInstancesConfig = defineInt('HELLO\_WORLD\_MININSTANCES');

export const helloWorld = onRequest(
  { minInstances: minInstancesConfig },
  (req, res) => {
    //…

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")

@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
    ...

بالإضافة إلى ذلك، إذا كنت بحاجة إلى المقارنة مع مَعلمة لمعرفة الخيار الذي يجب اختياره، عليك استخدام مقارِنين مضمّنين بدلاً من التحقّق من القيمة:

Node.js

const { onRequest } = require('firebase-functions/v2/https');
const environment = params.defineString(‘ENVIRONMENT’, {default: 'dev'});

// use built-in comparators
const minInstancesConfig = environment.equals('PRODUCTION').thenElse(10, 1);
export const helloWorld = onRequest(
  { minInstances: minInstancesConfig },
  (req, res) => {
    //…

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam, StringParam

ENVIRONMENT = StringParam("ENVIRONMENT", default="dev")
MIN_INSTANCES = ENVIRONMENT.equals("PRODUCTION").then(10, 0)

@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
    ...

يمكن الوصول إلى المَعلمات وتعبيرات المَعلمات التي يتم استخدامها في وقت التشغيل فقط من خلال دالة value الخاصة بها:

Node.js

const { onRequest } = require('firebase-functions/v2/https');
const { defineString } = require('firebase-functions/params');
const welcomeMessage = defineString('WELCOME_MESSAGE');

// To use configured parameters inside the config for a function, provide them
// directly. To use them at runtime, call .value() on them.
export const helloWorld = onRequest(
(req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

Python

from firebase_functions import https_fn
from firebase_functions.params import StringParam

WELCOME_MESSAGE = StringParam("WELCOME_MESSAGE")

@https_fn.on_request()
def hello_world(req):
    return https_fn.Response(f'{WELCOME_MESSAGE.value()}! I am a function!')

المعلمات المضمنة

تقدّم حزمة تطوير البرامج (SDK) لوظائف Cloud ثلاث مَعلمات محدّدة مسبقًا، وهي متاحة من الحزمة الفرعية firebase-functions/params:

Node.js

  • projectID: مشروع Cloud الذي يتم تشغيل الدالة فيه
  • databaseURL: عنوان URL لمثيل "قاعدة بيانات فورية الاستجابة" المرتبط بالدالة (إذا كان مفعّلاً في مشروع Firebase)
  • storageBucket: حزمة Cloud Storage المرتبطة بالدالة (في حال تفعيلها في مشروع Firebase)

Python

  • PROJECT_ID: مشروع Cloud الذي يتم تشغيل الدالة فيه
  • DATABASE_URL — عنوان URL لمثيل قاعدة البيانات في الوقت الفعلي المرتبط بالدالة (إذا كانت مفعّلة في مشروع Firebase)
  • STORAGE_BUCKET — حزمة Cloud Storage المرتبطة بالوظيفة (في حال تفعيلها في مشروع Firebase)

تعمل هذه الدوال مثل معلَمات السلسلة التي يحدّدها المستخدم في جميع الجوانب، باستثناء أنّه بما أنّ قيمها معروفة دائمًا في واجهة سطر الأوامر في Firebase، لن يُطلب منها أبدًا عند النشر ولن يتم حفظها في ملفات .env.

المَعلمات السرية

وتمثل المعلمات من النوع Secret، المحددة باستخدام defineSecret()، معلَمات السلسلة التي تحتوي على قيمة مخزنة في Cloud Secret Manager. بدلاً من التحقّق من ملف .env محلي وكتابة قيمة جديدة في الملف في حال عدم توفّره، تتحقّق مَعلمات المفتاح السري من توفّره في أداة "إدارة مفاتيح المرور في السحابة الإلكترونية"، وتطلب بشكل تفاعلي قيمة مفتاح سري جديد أثناء عملية النشر.

يجب ربط المَعلمات السرية المحدَّدة بهذه الطريقة بوظائف فردية يجب أن تملك إذن الوصول إليها:

Node.js

const { onRequest } = require('firebase-functions/v2/https');
const { defineSecret } = require('firebase-functions/params');
const discordApiKey = defineSecret('DISCORD_API_KEY');

export const postToDiscord = onRequest(
  { secrets: [discordApiKey] },
  (req, res) => {
  const apiKey = discordApiKey.value();
    //…

Python

from firebase_functions import https_fn
from firebase_functions.params import SecretParam

DISCORD_API_KEY = SecretParam('DISCORD_API_KEY')

@https_fn.on_request(secrets=[DISCORD_API_KEY])
def post_to_discord(req):
    api_key = DISCORD_API_KEY.value

نظرًا لأن قيم الأسرار مخفية حتى تنفيذ الدالة، لا يمكنك استخدامها أثناء تهيئة الدالة.

متغيرات البيئة

يتيح Cloud Functions for Firebase استخدام ملف dotenv لتحميل متغيّرات البيئة المحدّدة في ملف .env إلى وقت تنفيذ التطبيق. بعد نشر متغيرات البيئة، يمكن قراءتها من خلال واجهة process.env (في المشاريع المستندة إلى Node.js) أو os.environ (في المشاريع المستندة إلى Python).

لضبط بيئتك بهذه الطريقة، يمكنك إنشاء ملف .env في مشروعك وإضافة المتغيّرات المطلوبة ونشر ما يلي:

  1. أنشِئ ملف .env في دليل functions/:

    # Directory layout:
    #   my-project/
    #     firebase.json
    #     functions/
    #       .env
    #       package.json
    #       index.js
    
  2. افتح ملف .env لتعديله وأضِف المفاتيح المطلوبة. على سبيل المثال:

    PLANET=Earth
    AUDIENCE=Humans
    
  3. يمكنك نشر الدوال والتأكّد من تحميل متغيّرات البيئة:

    firebase deploy --only functions
    # ...
    # i functions: Loaded environment variables from .env.
    # ...
    

بمجرد نشر متغيرات البيئة المخصصة الخاصة بك، يمكن لرمز الدالة الوصول إليها:

Node.js

// Responds with "Hello Earth and Humans"
exports.hello = onRequest((request, response) => {
  response.send(`Hello ${process.env.PLANET} and ${process.env.AUDIENCE}`);
});

Python

import os

@https_fn.on_request()
def hello(req):
    return https_fn.Response(
        f"Hello {os.environ.get('PLANET')} and {os.environ.get('AUDIENCE')}"
    )

نشر مجموعات متعددة من متغيرات البيئة

إذا كنت بحاجة إلى مجموعة بديلة من متغيّرات البيئة لمشاريع Firebase (مثل التقسيم المرحلي مقابل الإنتاج)، أنشئ ملف .env.<project or alias> واكتب متغيّرات البيئة الخاصة بالمشروع هناك. سيتم تضمين متغيّرات البيئة من .env وملفات .env الخاصة بالمشروع (إن توفّرت) في جميع الدوال المنشورة.

على سبيل المثال، يمكن أن يتضمن المشروع هذه الملفات الثلاثة التي تحتوي على قيم مختلفة قليلاً للتطوير والإنتاج:

.env .env.dev .env.prod
PLANET=Earth

AUDIENCE=Humans

AUDIENCE=Dev Humans AUDIENCE=Prod Humans

بالنظر إلى القيم الموجودة في تلك الملفات المنفصلة، ستختلف مجموعة متغيرات البيئة التي تم نشرها مع الدوال بناءً على مشروعك المستهدف:

$ firebase use dev
$ firebase deploy --only functions
i functions: Loaded environment variables from .env, .env.dev.
# Deploys functions with following user-defined environment variables:
#   PLANET=Earth
#   AUDIENCE=Dev Humans

$ firebase use prod
$ firebase deploy --only functions
i functions: Loaded environment variables from .env, .env.prod.
# Deploys functions with following user-defined environment variables:
#   PLANET=Earth
#   AUDIENCE=Prod Humans

متغيّرات البيئة المحجوزة

بعض مفاتيح متغيّرات البيئة محجوزة للاستخدام الداخلي. لا تستخدم أيًا من هذه المفاتيح في ملفات .env:

  • جميع المفاتيح التي تبدأ بـ X_GOOGLE_
  • تبدأ جميع المفاتيح بـ EXT_
  • تبدأ كل المفاتيح بـ FIREBASE_
  • أي مفتاح من القائمة التالية:
  • CLOUD_RUNTIME_CONFIG
  • ENTRY_POINT
  • GCP_PROJECT
  • مشروع GCLOUD
  • مشروع GOOGLE_CLOUD
  • FUNCTION_TRIGGER_TYPE
  • FUNCTION_NAME
  • FUNCTION_MEMORY_MB
  • FUNCTION_TIMEOUT_SEC
  • FUNCTION_IDENTITY
  • FUNCTION_ AR
  • FUNCTION_TARGET
  • الوظيفة_SIGNATURE_TYPE
  • خدمة K_SERVICE
  • K_REVISION
  • PORT
  • الإعداد كيه

تخزين معلومات الضبط الحسّاسة والوصول إليها

يمكن استخدام متغيرات البيئة المخزَّنة في ملفات .env لإعداد الوظيفة، ولكن يجب ألّا تعتبرها طريقة آمنة لتخزين المعلومات الحساسة، مثل بيانات اعتماد قاعدة البيانات أو مفاتيح واجهة برمجة التطبيقات. وهذا مهم بشكل خاص إذا كنت تُراجع ملفات .env في أداة التحكّم في المصدر.

لمساعدتك في تخزين معلومات الإعداد الحسّاسة، يتم دمج Cloud Functions for Firebase مع Google Cloud Secret Manager. تخزِّن هذه الخدمة المشفَّرة قيم الضبط بشكل آمن، مع السماح بالوصول إليها بسهولة من الدوال عند الحاجة.

إنشاء مفتاح سرّي واستخدامه

لإنشاء واجهة برمجة تطبيقات سرّية، استخدِم واجهة سطر الأوامر Firebase.

لإنشاء مفتاح سرّي واستخدامه:

  1. من جذر دليل المشروع على الجهاز، نفِّذ الأمر التالي:

    firebase functions:secrets:set SECRET_NAME

  2. أدخِل قيمة في حقل SECRET_NAME.

    يعكس واجهة سطر الأوامر رسالة نجاح، ويحذّرك من ضرورة نشر وظائف لكي يتمّ تطبيق التغيير.

  3. قبل النشر، تأكد من أن رمز الدوال يسمح للدالة بالوصول إلى السر باستخدام المعلمة runWith:

    Node.js

    const { onRequest } = require('firebase-functions/v2/https');
    
    exports.processPayment = onRequest(
      { secrets: ["SECRET_NAME"] },
      (req, res) => {
        const myBillingService = initializeBillingService(
          // reference the secret value
          process.env.SECRET_NAME
        );
        // Process the payment
      }
    );

    Python

    import os
    from firebase_functions import https_fn
    
    @https_fn.on_request(secrets=["SECRET_NAME"])
    def process_payment(req):
        myBillingService = initialize_billing(key=os.environ.get('SECRET_NAME'))
        # Process the payment
        ...
    
  4. نشر Cloud Functions:

    firebase deploy --only functions

    ستتمكّن الآن من الوصول إليه مثل أي متغيّر بيئة آخر. وبالعكس، إذا حاولت دالة أخرى لا تحدّد المفتاح السرّي في runWith الوصول إلى المفتاح السرّي، ستتلقّى قيمة غير محدّدة:

    Node.js

    exports.anotherEndpoint = onRequest((request, response) => {
      response.send(`The secret API key is ${process.env.SECRET_NAME}`);
      // responds with "The secret API key is undefined" because the `runWith` parameter is missing
    });
    

    Python

    @https_fn.on_request()
    def another_endpoint(req):
        return https_fn.Response(f"The secret API key is {os.environ.get("SECRET_NAME")}")
        # Responds with "The secret API key is None" because the `secrets` parameter is missing.
    

بعد نشر الدالة، ستتمكّن من الوصول إلى القيمة السرية. ستتمكن الدوال فقط التي تتضمّن مفتاح سرّي في مَعلمة runWith من الوصول إلى هذا المفتاح السرّي على أنّه متغيّر بيئة. يساعدك ذلك في التأكّد من أنّ قيم الأسرار لا تتوفّر إلا عند الحاجة إليها، ما يقلل من خطر تسرُّب سرّ عن طريق الخطأ.

إدارة الأسرار

استخدِم واجهة برمجة التطبيقات Firebase لإدارة أسرارك. أثناء إدارة الأسرار بهذه الطريقة، تذكَّر أنّ بعض التغييرات في سطر الأوامر تتطلّب تعديل و/أو إعادة نشر الوظائف المرتبطة. على وجه التحديد:

  • عندما تقوم بتعيين قيمة جديدة لأحد المفاتيح، يجب إعادة نشر جميع الدوال التي تشير إلى هذا السر للحصول على أحدث قيمة.
  • إذا حذفت سرًا، تأكَّد من أنّ أيًا من وظائفك المنشورة لا تشير إلى هذا السر. الدوال التي تستخدم قيمة سرية تم حذفها ستفشل تلقائيًا.

في ما يلي ملخّص لأوامر واجهة سطر الأوامر Firebase للإدارة السرية:

# Change the value of an existing secret
firebase functions:secrets:set SECRET_NAME

# View the value of a secret
functions:secrets:access SECRET_NAME

# Destroy a secret
functions:secrets:destroy SECRET_NAME

# View all secret versions and their state
functions:secrets:get SECRET_NAME

# Automatically clean up all secrets that aren't referenced by any of your functions
functions:secrets:prune

بالنسبة إلى الأمرَين access وdestroy، يمكنك توفير مَعلمة الإصدار الاختيارية لإدارة إصدار معيّن. على سبيل المثال:

functions:secrets:access SECRET_NAME[@VERSION]

لمزيد من المعلومات عن هذه العمليات، أدخِل -h مع الأمر لاطلاع على مساعدة سطر الأوامر.

كيفية تحصيل رسوم مفاتيح المرور

تسمح Secret Manager بـ 6 إصدارات فعالة من الأسرار بدون أي تكلفة. وهذا يعني أنّه يمكنك الحصول على 6 أسرار شهريًا في مشروع Firebase بدون أي تكلفة.

يحاول واجهة سطر الأوامر Firebase تلقائيًا إتلاف الإصدارات السرية غير المستخدمة تلقائيًا عندما يكون ذلك مناسبًا، على سبيل المثال عندما تنشر دوال باستخدام إصدار جديد من المفتاح السرّي. يمكنك أيضًا إزالة المفاتيح السرّية غير المستخدَمة باستخدام functions:secrets:destroy وfunctions:secrets:prune.

تسمح Secret Manager بإجراء 10,000 عملية وصول شهرية غير مُحصَّلة رسومها على سر. لا تقرأ نُسخ الدوالّ إلا الأسرار المحدّدة في مَعلمة runWith في كل مرة يتم فيها تشغيلها بدون ذاكرة تخزين مؤقت. إذا كان لديك الكثير من نُسخ الدوالّ التي تقرأ الكثير من الأسرار، قد يتجاوز مشروعك هذا الحدّ المسموح به، وعندئذٍ سيتم تحصيل رسوم منك بقيمة 0.03 دولار أمريكي لكل 10,000 عملية وصول.

لمزيد من المعلومات، يُرجى الاطّلاع على أسعار "Secret Manager".

إتاحة استخدام المحاكيات

تم تصميم البيئة باستخدام dotenv للتشغيل التفاعلي مع مُحاكي Cloud Functions محلي.

عند استخدام محاكي Cloud Functions محلي، يمكنك إعداد ملف .env.local لإلغاء متغيّرات البيئة لمشروعك. يكون لمحتوىملف .env.local الأولوية على ملف.env وملف.env الخاص بالمشروع.

على سبيل المثال، يمكن أن يتضمّن المشروع الملفات الثلاثة التالية التي تحتوي على قيم مختلفة قليلاً للتطوير والاختبار على الجهاز:

.env .env.dev .env.local
PLANET=Earth

AUDIENCE=Humans

الجمهور=فريق مطوّري البرامج AUDIENCE=Local Humans

عند بدء تشغيل المحاكي في السياق المحلي، يحمّل متغيرات البيئة كما هو موضح:

  $ firebase emulators:start
  i  emulators: Starting emulators: functions
  # Starts emulator with following environment variables:
  #  PLANET=Earth
  #  AUDIENCE=Local Humans

الأسرار وبيانات الاعتماد في محاكي "Cloud Functions"

يتيح المحاكي Cloud Functions استخدام المفاتيح السرّية لتخزين معلومات الإعداد الحسّاسة والوصول إليها. سيحاول المحاكي بشكل تلقائي الوصول إلى المفاتيح السرّية للإنتاج باستخدام بيانات الاعتماد التلقائية للتطبيق. في بعض الحالات مثل بيئات CI، قد يتعذّر على المحاكي الوصول إلى القيم السرية بسبب قيود الأذونات.

على غرار توافق محاكي Cloud Functions مع متغيّرات البيئة، يمكنك تجاوز قيم الأسرار من خلال إعداد ملف .secret.local. يسهّل عليك ذلك اختبار الدوالّ على الجهاز، خاصةً إذا لم يكن لديك إذن بالوصول إلى القيمة السرية.

نقل البيانات من إعدادات البيئة

إذا كنت تستخدم إعدادات البيئة مع functions.config، يمكنك نقل إعداداتك الحالية كمتغيّرات بيئة (بتنسيق dotenv). توفّر واجهة Firebase CLI أمر تصدير يعرض ملف الإعدادات لكل عنوان بديل أو مشروع مُدرَج في ملف .firebaserc في الدليل (في المثال أدناه، local وdev وprod) كملفات .env.

لنقل البيانات، يمكنك تصدير إعدادات البيئة الحالية باستخدام الأمر firebase functions:config:export:

firebase functions:config:export
i  Importing configs from projects: [project-0, project-1]
⚠  The following configs keys could not be exported as environment variables:

⚠  project-0 (dev):
    1foo.a => 1FOO\_A (Key 1FOO\_A must start with an uppercase ASCII letter or underscore, and then consist of uppercase ASCII letters, digits, and underscores.)

Enter a PREFIX to rename invalid environment variable keys: CONFIG\_
✔  Wrote functions/.env.prod
✔  Wrote functions/.env.dev
✔  Wrote functions/.env.local
✔  Wrote functions/.env

يُرجى العِلم أنّه في بعض الحالات، سيُطلب منك إدخال بادئة لإعادة تسمية مفاتيح متغيّرات البيئة المُصدَّرة. ويرجع ذلك إلى أنّه لا يمكن تحويل جميع الإعدادات تلقائيًا لأنّها قد تكون غير صالحة أو قد تكون مفتاحًا لمتغيّر بيئة محجوزة.

ننصحك بمراجعة محتوى ملفات .env التي تم إنشاؤها بعناية قبل نشر الدوال أو التحقّق من ملفات .env في عنصر التحكّم في المصدر. إذا كانت أي قيم حسّاسة ويجب عدم تسريبها، عليك إزالتها من ملفاتك في .env وحفظها بأمان في Secret Manager بدلاً من ذلك.

ستحتاج أيضًا إلى تحديث رمز الدوال. أي دوالّ تستخدم functions.config ستحتاج الآن إلى استخدام process.env بدلاً من ذلك، كما هو موضّح في متغيّرات البيئة.