firebase / firebase-functions-python Goto Github PK
View Code? Open in Web Editor NEWLicense: Apache License 2.0
License: Apache License 2.0
I'm following the start guide at: https://firebase.google.com/docs/functions/get-started?gen=2nd
At step 7, when testing the functions using the emulator, the addmessage
function works fine, and triggers the makeuppercase
function appropriately, but the makeuppercase
call fails with an error related to event datetime:
i functions: Beginning execution of "us-central1-addmessage"
> 127.0.0.1 - - [21/May/2023 01:57:15] "GET /?text=newmessage HTTP/1.1" 200 -
i functions: Finished "us-central1-addmessage" in 105.1165ms
> * Serving Flask app 'makeuppercase'
> * Debug mode: off
> WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
> * Running on http://127.0.0.1:8933
> Press CTRL+C to quit
> 127.0.0.1 - - [21/May/2023 01:57:16] "GET /__/health HTTP/1.1" 405 -
i functions: Beginning execution of "us-central1-makeuppercase"
> [2023-05-21 01:57:16,487] ERROR in app: Exception on /functions/projects/ [POST]
> Traceback (most recent call last):
> File "C:\Users\user\proj\functions\venv\Lib\site-packages\flask\app.py", line 2190, in wsgi_app
> response = self.full_dispatch_request()
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "C:\Users\user\proj\functions\venv\Lib\site-packages\flask\app.py", line 1486, in full_dispatch_request
> rv = self.handle_user_exception(e)
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "C:\Users\user\proj\functions\venv\Lib\site-packages\flask\app.py", line 1484, in full_dispatch_request
> rv = self.dispatch_request()
> ^^^^^^^^^^^^^^^^^^^^^^^
> File "C:\Users\user\proj\functions\venv\Lib\site-packages\flask\app.py", line 1469, in dispatch_request
> return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "C:\Users\user\proj\functions\venv\Lib\site-packages\functions_framework\__init__.py", line 174, in view_func
> function(event)
> File "C:\Users\user\proj\functions\venv\Lib\site-packages\firebase_functions\firestore_fn.py", line 302, in on_document_created_wrapped
> return _firestore_endpoint_handler(
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "C:\Users\user\proj\functions\venv\Lib\site-packages\firebase_functions\firestore_fn.py", line 114, in _firestore_endpoint_handler
> event_time = _dt.datetime.strptime(
> ^^^^^^^^^^^^^^^^^^^^^^
> File "C:\Python311\Lib\_strptime.py", line 568, in _strptime_datetime
> tt, fraction, gmtoff_fraction = _strptime(data_string, format)
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "C:\Python311\Lib\_strptime.py", line 349, in _strptime
> raise ValueError("time data %r does not match format %r" %
> ValueError: time data '2023-05-21T01:57:15.643674100Z' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'
i functions: Finished "us-central1-makeuppercase" in 22.0598ms
> 127.0.0.1 - - [21/May/2023 01:57:16] "POST /functions/projects/ HTTP/1.1" 500 -
FWIW, I was able to hack around it locally by modifying firestore_fn.py to use dateutil.parser instead and changing line 114:
import dateutil.parser as dateutil
Line 114:
event_time = dateutil.parse(event_attributes["time"])
Not sure if this would be the most appropriate fix for the repo, or if there's some other underlying root cause that should be addressed.
Not a rep for Mendable, just tired of having to read, reread, and reread again documentation to get a basic thing working.
Please get Mendable and hook it up to y'alls documentation. It has been great when reading Langchain docs.
Hello! ๐
There is a bug in the logic to generate the "after" state of a (realtime) database change. The bug appears to be in the below lines of code, only a shallow copy/merge is performed but a deep one is needed.
firebase-functions-python/src/firebase_functions/db_fn.py
Lines 92 to 94 in 14676e5
As an example of a failure case, I had just changed allocation/change
from F
to G
in the following:
However I have a listener setup on the root object of the screenshot and the event.data
object that is generated by that change was:
Change(
before={'allocation': {'change': 'F', 'role': 'admin', 'third': 3}, 'details': <redacted>},
after={'allocation': {'change': 'G'}, 'details': <redacted>})
It should be:
Change(
before={'allocation': {'change': 'F', 'role': 'admin', 'third': 3}, 'details': <redacted>},
after={'allocation': {'change': 'G', 'role': 'admin', 'third': 3}, 'details': <redacted>})
Let me know if you need any more info.
Thanks!
Moved back to back log - change breaks a few things so internals needs a bit of a refactor. This bug is also present on JS Functions implementation
The triggers described here are not available yet in the library: https://firebase.google.com/docs/functions/auth-events
While not yet officially available, firebase/firebase-tools#5592 indicates that they soon will be.
In JS/Node SDK, both form of document path are accepted:
document="/messages/{messageId}"
document="messages/{messageId}"
This is done by normalizing document path (code).
This "magic" is missing in the python sdk.
Hello,
I'm migrating from JS to Python, but my functions are deployed in US and I'm in France/Europe.
How can I set deployement region ?
before in JS :
import * as firebaseFunctions from "firebase-functions";
export const fonctions = firebaseFunctions.region("europe-west1");
Thinks for the lib,
When I run the below code in the emulator or in a deployed function, it always prints an empty string:
from firebase_functions import https_fn, params
maps_api_key = params.SecretParam("MAPS_API_KEY")
@https_fn.on_request(timeout_sec=20)
def speciesinarea(req: https_fn.Request) -> https_fn.Response:
print("maps key: {}".format(maps_api_key.value()))
return https_fn.Response('OK')
If I run functions:secrets:access MAPS_API_KEY
, the CLI does return the correct API key, so I know the value is set in Secret Manager.
For the emulators, setting values in a .secret.local
file does result in the SDK returning a secret value when run in the emulator. But by default, the docs say that the emulator should access the secret value from Secret Manager.
This error pops up every time I call a function after starting the emulators.
... [call stack omitted]
> Message: 'Request has invalid method.'
> Arguments: ('GET',)
> ERROR:root:Invalid request, unable to process.
I'm using an @https_fn.on_call
and calling it with curl -X POST
so the GET
in there is a bit confusing. Moreover, this just shows up - it doesn't degrade functionality much aside from potentially delaying the cold-start.
The functions work just fine... but this long stack trace on a cold-start is troubling.
I have a long-running (~75s) Python cloud function that works with the emulator and also works when deployed. But intermittingly, it fails in the emulator with the error:
Failed to handle request for function us-central1-script_infer_api
FirebaseError: Failed to load function
The function signature is:
@https_fn.on_request(timeout_sec=300, memory=options.MemoryOption.GB_2)
def script_infer_api(req: https_fn.Request) -> https_fn.Response:
I ran the emulator in verbose mode but it didn't tell me anything more, either. Is there another way to increase the logging?
Firebase cli: version 12.3.1 (latest)
Hello everyone,
I am writing this email to address some challenges we've encountered while attempting to deploy Firebase functions. Currently, when we deploy a single function using the command "firebase deploy --only functions:function_name," the deployment process works smoothly and the function is correctly deployed. However, when we utilize the command "firebase deploy --only functions" to deploy all functions, we're encountering an issue where all the functions end up with the same container image URL. As a result, this is causing requests to be directed to only one function instead of the intended target functions.
Thank you.
Just running the main.py locally works.
Referencing a sub folder as a module
tree:
- test
- - __init__.py
- - base.py
- main.py
in main.py:
from test import base
def some_function():
base.testFunc()
if __name__ == "__main__":
some_function()
When deploying the function, or when running emulators locally with firebase emulators:start
ModuleNotFoundError: No module named 'test'
When running python main.py
everything works as expected
[REQUIRED] Environment info
firebase-tools:12.4.7
Platform: windows with python version of 3.11
[REQUIRED] Test case
i have code like below in for firebase cloud function in main.py.
when i test function using firebase emulators:start --only functions
it worked perfectly
now when i try to deploy it using firebase deploy --only functions
it gave me below error while pointing to db = firestore.client()
line in code
error
"""""""""
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
"""""""""
code
"""
from firebase_functions import https_fn, options
import firebase_admin
from firebase_admin import firestore
app = firebase_admin.initialize_app()
options.set_global_options(timeout_sec=1000)
db = firestore.client()
"""
[REQUIRED] Steps to reproduce
use above code in main.py inside functions folder and try to deploy functions you will get same error
[REQUIRED] Expected behavior
credential should be automatically added since i am logged into my account using firebase login and using correct Project ID. it did not ask for credential when i was tasing using firebase emulators:start --only functions
and it was working perfectly.
[REQUIRED] Actual behavior
it's asking for credential
Create a Python equivalent of the Node logger
subpackage to integrate with Cloud Logging's structured logs
Also include trace; https://github.com/firebase/firebase-functions/blob/aae1abd55930550636e8e95c41feefcb617edc9d/src/common/trace.ts#L6
Should allow parameters to be included in reference strings
Hi Folks. So I am Having issues Connecting the local firebase emulator with python firebase functions.recently i was trying to migrate my javascript code to python to leverage the python libraries and its ecosystem. If i use a Callable function in javascript to write data to the firebase with firebase Admin privilege it does so, but when i am trying to use with python, The Callable function gets called but if use the firebase Admin package to write data to the firestore the data are not written. is there Anything that I am Missing?
MacOS Ventura with Python 3.11 and venv.
Passing a list[SecretParam] as the value of secrets= like this:
DISCORD_WEBHOOK_URL = params.SecretParam("DISCORD_WEBHOOK_URL")
@crashlytics_fn.on_new_fatal_issue_published(secrets=[DISCORD_WEBHOOK_URL])
Causes this error:
- FirebaseError HTTP Error: 400, The provided Secret Version ID [projects/1718007911/secrets/{{ params.DISCORD_WEBHOOK_URL }}/versions/latest] does not match the expected format [projects/*/secrets/*/versions/*]
secrets=["DISCORD_WEBHOOK_URL"]
works as expected.
It looks plain retry
boolean is supported, but not RetryConfig
in order to specify backoff and max attempts.
Thanks.
I'm following the example from the samples
folder; the function is not printing anything. The emulator is configuring it without any issues but is not doing what it is supposed to.
Implementation of Pub/Sub functions support.
PR: #11
I'm using Ubuntu 22.04 and I'm running into an error emulating and deploying my python functions.
From my firebase-debug.log:
debug] [2023-03-27T20:07:25.697Z] Customer code is not Node
[debug] [2023-03-27T20:07:25.698Z] Validating python source
[debug] [2023-03-27T20:07:25.698Z] Building python source
[debug] [2023-03-27T20:07:25.698Z] Could not find functions.yaml. Must use http discovery
[debug] [2023-03-27T20:07:25.699Z] Running command with virtualenv: command=source, args=["/home/rafael/dev/protea/web/firebase-functions-python/venv/bin/activate","&&","python3.10","-c","\"import firebase_functions; import os; print(os.path.dirname(firebase_functions.__file__))\""]
[debug] [2023-03-27T20:07:25.707Z] Running admin server with args: ["python3.10","private/serving.py"] and env: {"FIREBASE_CONFIG":"{\"projectId\":\"protea-technology-services\",\"storageBucket\":\"protea-technology-services.appspot.com\",\"locationId\":\"us-central\"}","GCLOUD_PROJECT":"protea-technology-services","ADMIN_PORT":"8081"} in /home/rafael/dev/protea/web/firebase-functions-python
[debug] [2023-03-27T20:07:25.707Z] Running command with virtualenv: command=source, args=["/home/rafael/dev/protea/web/firebase-functions-python/venv/bin/activate","&&","python3.10","private/serving.py"]
[debug] [2023-03-27T20:07:25.714Z] stderr: /bin/sh: 1: source: not found
[debug] [2023-03-27T20:07:56.225Z] FetchError: request to http://127.0.0.1:8081/__/quitquitquit failed, reason: connect ECONNREFUSED 127.0.0.1:8081
at ClientRequest.<anonymous> (/home/rafael/.nvm/versions/node/v16.19.1/lib/node_modules/firebase-tools/node_modules/node-fetch/lib/index.js:1491:11)
at ClientRequest.emit (node:events:513:28)
at ClientRequest.emit (node:domain:489:12)
at Socket.socketErrorListener (node:_http_client:494:9)
at Socket.emit (node:events:513:28)
at Socket.emit (node:domain:489:12)
at emitErrorNT (node:internal/streams/destroy:157:8)
at emitErrorCloseNT (node:internal/streams/destroy:122:3)
at processTicksAndRejections (node:internal/process/task_queues:83:21)
[error]
[error] Error: An unexpected error has occurred.
Local module import still doesn't work.
I am using the recommended python version 3.11 and the latest firebase-functions-python==0.1.1
[fix: add cwd to sys.path for functions yaml] #12
Do python cloud functions support async
and await
? I can't find any examples showing this but it seems like a pretty basic feature. Am I missing it?
Implementation of Storage functions support.
PR; #13
I'm writing a function with a realtime DB trigger.
@db_fn.on_value_created(reference="/messages/{user}/{chat_id}/{msg_id}")
def do_work(event: db_fn.Event[Any]) -> None:
# process event
From reading the docs, I expect this to match on a message pushed to a chat with chat_id. For example, a value created at /messages/user_1/chat_1/msg_a
would be captured and the appropriate ids sent to the function.
However, when I attempt to implement this functionality, errors crop up in the pattern matching code:
File "/layers/google.python.pip/pip/lib/python3.11/site-packages/firebase_functions/private/path_pattern.py", line 177, in extract_matches
matches[segment.trimmed] = path_segments[path_ndx]
~~~~~~~~~~~~~^^^^^^^^^^
IndexError: list index out of range
It seems like the pattern-matching code errors out in this situation where the value created is at a ref with a wildcard in the last path segment. I'm using a workaround right now but thought I'd bring it up as an issue.
Hey Team,
I'm currently trying to use a POST to a firebase function and am having some issues. I tried it both with vanilla functions and exposing it through a flask app.
Here's the gist with code trying with flask and without.
The GET works fine. the POST I see an options call succeed, then never see the post actually get invoked.
It works in an emulator, but not when I deploy it out. For this example I've enabled cors and allowed GET and POST on all origins.
Here is the network tab with my UI making the call
Here is the firebase function log. As you can see the option call shows up 200, but then nothing
Any ideas?
Using the simplest possible example for on_document_created
returns this error:
ValueError: time data '2023-06-16T00:34:08.115125300Z' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'
Function:
@firestore_fn.on_document_created(document="messages/{pushId}")
def makeuppercase(
event: firestore_fn.Event[firestore_fn.DocumentSnapshot | None],
) -> None:
print("foo")
return
Full error:
functions: Beginning execution of "us-central1-makeuppercase"
> 2023-06-16 00:34:09,461 - 31024 - app.py-app:1414 - ERROR: Exception on /functions/projects/ [POST]
> Traceback (most recent call last):
> File "D:\dev\rbt\ml\functions\venv\lib\site-packages\flask\app.py", line 2190, in wsgi_app
> response = self.full_dispatch_request()
> File "D:\dev\rbt\ml\functions\venv\lib\site-packages\flask\app.py", line 1486, in full_dispatch_request
> rv = self.handle_user_exception(e)
> File "D:\dev\rbt\ml\functions\venv\lib\site-packages\flask\app.py", line 1484, in full_dispatch_request
> rv = self.dispatch_request()
> File "D:\dev\rbt\ml\functions\venv\lib\site-packages\flask\app.py", line 1469, in dispatch_request
> return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
> File "D:\dev\rbt\ml\functions\venv\lib\site-packages\functions_framework\__init__.py", line 174, in view_func
> function(event)
> File "D:\dev\rbt\ml\functions\venv\lib\site-packages\firebase_functions\firestore_fn.py", line 302, in on_document_created_wrapped
> return _firestore_endpoint_handler(
> File "D:\dev\rbt\ml\functions\venv\lib\site-packages\firebase_functions\firestore_fn.py", line 114, in _firestore_endpoint_handler
> event_time = _dt.datetime.strptime(
> File "C:\Users\jonat\.pyenv\pyenv-win\versions\3.10.6\lib\_strptime.py", line 568, in _strptime_datetime
> tt, fraction, gmtoff_fraction = _strptime(data_string, format)
> File "C:\Users\jonat\.pyenv\pyenv-win\versions\3.10.6\lib\_strptime.py", line 349, in _strptime
> raise ValueError("time data %r does not match format %r" %
> ValueError: time data '2023-06-16T00:34:08.115125300Z' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'
Tier 2 regions should be included in SupportedRegion
:
firebase-functions-python/src/firebase_functions/options.py
Lines 92 to 103 in 59d68cf
See firebase/firebase-functions#1397 for more context
In this example, the Crashlytics trigger fails because it's calling value()
on a SecretParam
and getting an empty string.
But, if I add options.set_global_options(secrets=["DISCORD_WEBHOOK_URL"])
, the trigger works as expected.
Implementation of Alerts functions support.
I just tried firebase deploy --only functions
but if you see the line python3.11 "/Users/sushi/Development/sushi-verse/fb/functions-py/venv/lib/python3.11/site-packages/firebase_functions/private/serving.py
it exits the shell very early on.
I was just trying this with the 2nd Gen Tutorial Page.
My guess is that it does not work with Python 3.11, but there is no explicit version requirement so far, I cannot find,
MacOS Ventura with Python 3.11 and venv
The names of the user and project have been altered from my own username and project.
(venv) sushi@mtmbp functions-py % firebase deploy --only functions
=== Deploying to 'sushiverse-fa'...
i deploying functions
i functions: preparing codebase default for deployment
i functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i functions: ensuring required API cloudbuild.googleapis.com is enabled...
i artifactregistry: ensuring required API artifactregistry.googleapis.com is enabled...
โ artifactregistry: required API artifactregistry.googleapis.com is enabled
โ functions: required API cloudfunctions.googleapis.com is enabled
โ functions: required API cloudbuild.googleapis.com is enabled
i functions: Loading and anaylzing source code for codebase default to determine what to deploy
* Serving Flask app 'serving'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:8081
Press CTRL+C to quit
127.0.0.1 - - [04/Jul/2023 16:55:26] "GET /__/functions.yaml HTTP/1.1" 200 -
127.0.0.1 - - [04/Jul/2023 16:55:26] "GET /__/quitquitquit HTTP/1.1" 200 -
/bin/sh: line 1: 91546 Terminated: 15 python3.11 "/Users/sushi/Development/sushi-verse/fb/functions-py/venv/lib/python3.11/site-packages/firebase_functions/private/serving.py"
i functions: preparing functions-py directory for uploading...
i functions: packaged /Users/sushi/Development/sushi-verse/fb/functions-py (6.03 KB) for uploading
i functions: ensuring required API run.googleapis.com is enabled...
i functions: ensuring required API eventarc.googleapis.com is enabled...
i functions: ensuring required API pubsub.googleapis.com is enabled...
i functions: ensuring required API storage.googleapis.com is enabled...
โ functions: required API run.googleapis.com is enabled
โ functions: required API eventarc.googleapis.com is enabled
โ functions: required API pubsub.googleapis.com is enabled
โ functions: required API storage.googleapis.com is enabled
i functions: generating the service identity for pubsub.googleapis.com...
i functions: generating the service identity for eventarc.googleapis.com...
i functions: Skipping the deploy of unchanged functions with experimental support for skipdeployingnoopfunctions
โ functions[addmessage(us-central1)] Skipped (No changes detected)
โ functions[makeuppercase(us-central1)] Skipped (No changes detected)
i functions: cleaning up build files...
Implementation of Tasks functions support.
Notes;
https.unsafeDecodeIdToken(token)
for auth dataThe docs state that the cors
attribute may be True to allow all origins or a str for an allowed origin
but this is not the case in usage.
The type for cors is CorsOptions
which I could not find anywhere within the firebase functions or admin library.
Is CorsOptions a flask implementation? How can I allow my web app to communicate with the endpoint? Can I set cors globally?
This is on the emulator with v0.1.1. I have not tested this as a deployed function.
Not sure if this is my mistake, but I can't seem to access the secrets from within a Firestore function, although the secrets parameter looks like it is defined in _GLOBAL_OPTIONS?
from firebase_functions import firestore_fn
from firebase_admin import initialize_app, firestore
from firebase_functions.params import SecretParam
app = initialize_app()
db = firestore.client()
SECRET_KEY_ONE = SecretParam("SECRET_KEY_ONE")
SECRET_KEY_TWO = SecretParam("SECRET_KEY_TWO")
@firestore_fn.on_document_created(document="Chat/{chatId}", secrets=[SECRET_KEY_ONE, SECRET_KEY_TWO])
def onChatCreated(
event: firestore_fn.Event[firestore_fn.DocumentSnapshot | None]
) -> None:
print(SECRET_KEY_ONE.value())
return
Gives me
TypeError: 'str' object is not callable
When I change the code to
print(SECRET_KEY_ONE)
it gives me {{ params.SECRET_KEY_ONE }}
The secrets are defined in Cloud Secrets. When I change the secrets' names, it asks me to save a new value, indicating that it is aware of their existence of their original names in Cloud Secrets.
When an unlabeled test triggers on_test_matrix_completed
, it throws the following:
Traceback (most recent call last):
File "/layers/google.python.pip/pip/lib/python3.10/site-packages/flask/app.py", line 2528, in wsgi_app
response = self.full_dispatch_request()
File "/layers/google.python.pip/pip/lib/python3.10/site-packages/flask/app.py", line 1825, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/layers/google.python.pip/pip/lib/python3.10/site-packages/flask/app.py", line 1823, in full_dispatch_request
rv = self.dispatch_request()
File "/layers/google.python.pip/pip/lib/python3.10/site-packages/flask/app.py", line 1799, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
File "/layers/google.python.pip/pip/lib/python3.10/site-packages/functions_framework/__init__.py", line 174, in view_func
function(event)
File "/layers/google.python.pip/pip/lib/python3.10/site-packages/firebase_functions/test_lab_fn.py", line 273, in on_test_matrix_completed_wrapped
return _event_handler(func, raw)
File "/layers/google.python.pip/pip/lib/python3.10/site-packages/firebase_functions/test_lab_fn.py", line 225, in _event_handler
details=event_data["clientInfo"]["details"],
KeyError: 'details'
I'm raising https_fn.HttpsError
with various code=https_fn.FunctionsErrorCode.XYZ
from within an @https_fn.on_request()
-decorated function to test error paths. But if I throw e.g. ostensibly a 400 (FunctionsErrorCode.NOT_FOUND
) the caller gets a 500. It doesn't matter what type of error I throw. Is this intentional for on_request
? I'd love to have more granular HTTP errors.
Anyway, thanks very much for a lovely Python3 SDK for FB Functions - it's a super convenient service.
This is feedback for the firebase-tools repo, adding it here just because it's related to the Python EAP.
Running firebase init functions
results in invalid functions code.
import
is incorrect. In the template, it is from firebase_functions import https
, but it should be from firebase_functions import https_fn
.firebase_admin
is missing from requirements.txt
https
should be renamed to https_fn
in the function codeHello! After updating to the latest versions of the firebase function and firebase tools, I am still running into the issue where my "main.py" file does not found the module "flask_restful" when i try uploading it to cloud via "firebase deploy --only functions". I have already included "flask_restful" and its version in the "requirements.txt" file under the "functions" folder, however, it still does not recognize it. Any advice?
firebase-tools: tried with both 12.2.1 and 12.3.1 in GitHub Actions. Locally I've been using 12.2.1
Platform: Local is macOS and GitHub Actions is Ubuntu
This is my bare bones cloud function:
import firebase_admin
from firebase_admin import firestore, initialize_app
from google.cloud.firestore_v1.base_query import FieldFilter
from firebase_functions.firestore_fn import (
on_document_created,
Event,
DocumentSnapshot,
)
initialize_app()
db = firestore.client()
@on_document_created(document="sessions/{sessionId}")
def on_create_session(event: Event[DocumentSnapshot | None]) -> None:
print('Hi there')
I have a functions folder at the root of my project with python functions (everything is working with emulator). In my local I follow these steps:
cd functions
python3.11 -m venv venv
. venv/bin/activate
python3.11 -m pip install -r requirements.txt
export GOOGLE_APPLICATION_CREDENTIALS=path/to/my/service-account.json
npx firebase-tools deploy --only functions
The above works when logged out of Firebase. If logged into firebase, I skip setting up the GOOGLE_APPLICATION_CREDENTIALS env variable and everything works fine. I've tested both scenarios multiple times (and it in different terminals) and am able to deploy my cloud functions fine.
However, I do exactly the same steps in my GitHub actions and run into an error. Both my Node (19.7.0) and Python (3.11) versions are the same between my local and GitHub actions. I had also tried with Node 18 to no effect. Here is my GitHub Actions config:
name: Deploy to DEV
"on":
push:
branches:
- main
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.11
- name: Set up Node
uses: actions/setup-node@v3
with:
node-version: 19.7.0
- name: Create SA key
run: echo '${{ secrets.FIREBASE_SERVICE_ACCOUNT_DEV }}' > $HOME/gcloud.json
- name: Deploy Cloud Functions
working-directory: functions
run: |
python3.11 -m venv venv
. venv/bin/activate
npx firebase-tools --version
python3.11 -m pip install -r requirements.txt
export GOOGLE_APPLICATION_CREDENTIALS=$HOME/gcloud.json
npx firebase-tools deploy --only functions --debug
- name: Deploy Firestore Rules
run: |
export GOOGLE_APPLICATION_CREDENTIALS=$HOME/gcloud.json
npx firebase-tools deploy --only firestore:rules
Just a note, Deploy Firestore Rules works fine by itself so I know the credentials are valid in the pipeline too.
Functions should deploy same as on my local.
The error that I get when Deploy Cloud Functions runs is:
Notice: A new release of pip available: 22.3.1 -> 23.1.2
Notice: To update, run: pip install --upgrade pip
npm WARN exec The following package was not found and will be installed: [email protected]
npm WARN deprecated @npmcli/[email protected]: This functionality has been moved to @npmcli/fs
npm WARN deprecated [email protected]: this library is no longer supported
npm WARN deprecated [email protected]: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated [email protected]: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
[2023-06-09T22:15:01.093Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
[2023-06-09T22:15:01.172Z] [iam] checking project *** for permissions ["cloudfunctions.functions.create","cloudfunctions.functions.delete","cloudfunctions.functions.get","cloudfunctions.functions.list","cloudfunctions.functions.update","cloudfunctions.operations.get","firebase.projects.get"]
[2023-06-09T22:15:01.172Z] >>> [apiv2][query] POST https://cloudresourcemanager.googleapis.com/v1/projects/***:testIamPermissions [none]
[2023-06-09T22:15:01.173Z] >>> [apiv2][(partial)header] POST https://cloudresourcemanager.googleapis.com/v1/projects/***:testIamPermissions x-goog-quota-user=projects/***
[2023-06-09T22:15:01.173Z] >>> [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/***:testIamPermissions ***"permissions":["cloudfunctions.functions.create","cloudfunctions.functions.delete","cloudfunctions.functions.get","cloudfunctions.functions.list","cloudfunctions.functions.update","cloudfunctions.operations.get","firebase.projects.get"]***
[2023-06-09T22:15:01.196Z] <<< [apiv2][status] GET https://firebase-public.firebaseio.com/cli.json 200
[2023-06-09T22:15:01.196Z] <<< [apiv2][body] GET https://firebase-public.firebaseio.com/cli.json ***"cloudBuildErrorAfter":1594252800000,"cloudBuildWarnAfter":1590019200000,"defaultNode10After":1594252800000,"minVersion":"3.0.5","node8DeploysDisabledAfter":1613390400000,"node8RuntimeDisabledAfter":1615809600000,"node8WarnAfter":1600128000000***
[2023-06-09T22:15:01.248Z] <<< [apiv2][status] POST https://cloudresourcemanager.googleapis.com/v1/projects/***:testIamPermissions 200
[2023-06-09T22:15:01.249Z] <<< [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/***:testIamPermissions ***"permissions":["cloudfunctions.functions.create","cloudfunctions.functions.delete","cloudfunctions.functions.get","cloudfunctions.functions.list","cloudfunctions.functions.update","cloudfunctions.operations.get","firebase.projects.get"]***
[2023-06-09T22:15:01.250Z] >>> [apiv2][query] POST https://iam.googleapis.com/v1/projects/***/serviceAccounts/***@appspot.gserviceaccount.com:testIamPermissions [none]
[2023-06-09T22:15:01.250Z] >>> [apiv2][body] POST https://iam.googleapis.com/v1/projects/***/serviceAccounts/***@appspot.gserviceaccount.com:testIamPermissions ***"permissions":["iam.serviceAccounts.actAs"]***
[2023-06-09T22:15:01.328Z] <<< [apiv2][status] POST https://iam.googleapis.com/v1/projects/***/serviceAccounts/***@appspot.gserviceaccount.com:testIamPermissions 200
[2023-06-09T22:15:01.328Z] <<< [apiv2][body] POST https://iam.googleapis.com/v1/projects/***/serviceAccounts/***@appspot.gserviceaccount.com:testIamPermissions ***"permissions":["iam.serviceAccounts.actAs"]***
=== Deploying to '***'...
i deploying functions
[2023-06-09T22:15:01.335Z] >>> [apiv2][query] GET https://firebase.googleapis.com/v1beta1/projects/*** [none]
[2023-06-09T22:15:01.582Z] <<< [apiv2][status] GET https://firebase.googleapis.com/v1beta1/projects/*** 200
[2023-06-09T22:15:01.582Z] <<< [apiv2][body] GET https://firebase.googleapis.com/v1beta1/projects/*** ***"projectId":"***","projectNumber":"***","displayName":"***","name":"projects/***","resources":***"hostingSite":"***","storageBucket":"***","locationId":"us-central"***,"state":"ACTIVE","etag":"1_a7d5abaf-d82c-4064-9d46-2e0d08b0818d"***
i functions: preparing codebase default for deployment
i functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i functions: ensuring required API cloudbuild.googleapis.com is enabled...
i artifactregistry: ensuring required API artifactregistry.googleapis.com is enabled...
[2023-06-09T22:15:01.584Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/***/services/cloudfunctions.googleapis.com [none]
[2023-06-09T22:15:01.584Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/***/services/cloudfunctions.googleapis.com x-goog-quota-user=projects/***
[2023-06-09T22:15:01.586Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/***/services/runtimeconfig.googleapis.com [none]
[2023-06-09T22:15:01.586Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/***/services/runtimeconfig.googleapis.com x-goog-quota-user=projects/***
[2023-06-09T22:15:01.587Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/***/services/cloudbuild.googleapis.com [none]
[2023-06-09T22:15:01.588Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/***/services/cloudbuild.googleapis.com x-goog-quota-user=projects/***
[2023-06-09T22:15:01.589Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/***/services/artifactregistry.googleapis.com [none]
[2023-06-09T22:15:01.589Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/***/services/artifactregistry.googleapis.com x-goog-quota-user=projects/***
[2023-06-09T22:15:01.877Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/***/services/runtimeconfig.googleapis.com 200
[2023-06-09T22:15:01.877Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/***/services/runtimeconfig.googleapis.com [omitted]
[2023-06-09T22:15:01.902Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/***/services/artifactregistry.googleapis.com 200
[2023-06-09T22:15:01.902Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/***/services/artifactregistry.googleapis.com [omitted]
โ artifactregistry: required API artifactregistry.googleapis.com is enabled
[2023-06-09T22:15:01.907Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/***/services/cloudbuild.googleapis.com 200
[2023-06-09T22:15:01.907Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/***/services/cloudbuild.googleapis.com [omitted]
โ functions: required API cloudbuild.googleapis.com is enabled
[2023-06-09T22:15:01.910Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/***/services/cloudfunctions.googleapis.com 200
[2023-06-09T22:15:01.911Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/***/services/cloudfunctions.googleapis.com [omitted]
โ functions: required API cloudfunctions.googleapis.com is enabled
[2023-06-09T22:15:01.911Z] >>> [apiv2][query] GET https://firebase.googleapis.com/v1beta1/projects/***/adminSdkConfig [none]
[2023-06-09T22:15:02.050Z] <<< [apiv2][status] GET https://firebase.googleapis.com/v1beta1/projects/***/adminSdkConfig 200
[2023-06-09T22:15:02.050Z] <<< [apiv2][body] GET https://firebase.googleapis.com/v1beta1/projects/***/adminSdkConfig ***"projectId":"***","storageBucket":"***","locationId":"us-central"***
[2023-06-09T22:15:02.053Z] >>> [apiv2][query] GET https://runtimeconfig.googleapis.com/v1beta1/projects/***/configs [none]
[2023-06-09T22:15:02.277Z] <<< [apiv2][status] GET https://runtimeconfig.googleapis.com/v1beta1/projects/***/configs 200
[2023-06-09T22:15:02.277Z] <<< [apiv2][body] GET https://runtimeconfig.googleapis.com/v1beta1/projects/***/configs ***
[2023-06-09T22:15:02.278Z] Customer code is not Node
[2023-06-09T22:15:02.279Z] Validating python source
[2023-06-09T22:15:02.279Z] Building python source
[2023-06-09T22:15:02.280Z] Could not find functions.yaml. Must use http discovery
[2023-06-09T22:15:02.285Z] Running command with virtualenv: command=., args=["\"/home/runner/work/myapp-web/myapp-web/functions/venv/bin/activate\"","&&","python3.11","-c","\"import firebase_functions; import os; print(os.path.dirname(firebase_functions.__file__))\""]
[2023-06-09T22:15:02.324Z] stdout: /home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_functions
[2023-06-09T22:15:02.329Z] Running admin server with args: ["python3.11","\"/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_functions/private/serving.py\""] and env: ***"FIREBASE_CONFIG":"***\"projectId\":\"***\",\"storageBucket\":\"***\",\"locationId\":\"us-central\"***","GCLOUD_PROJECT":"***","ADMIN_PORT":"8081"*** in /home/runner/work/myapp-web/myapp-web/functions
[2023-06-09T22:15:02.329Z] Running command with virtualenv: command=., args=["\"/home/runner/work/myapp-web/myapp-web/functions/venv/bin/activate\"","&&","python3.11","\"/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_functions/private/serving.py\""]
[2023-06-09T22:15:02.926Z] stdout: * Serving Flask app 'serving'
* Debug mode: off
[2023-06-09T22:15:02.928Z] stderr: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:8081
Press CTRL+C to quit
[2023-06-09T22:15:03.191Z] stderr: [2023-06-09 22:15:03,188] ERROR in app: Exception on /__/functions.yaml [GET]
Traceback (most recent call last):
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/flask/app.py", line 2190, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/flask/app.py", line 1486, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/flask/app.py", line 1484, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/flask/app.py", line 1469, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_functions/private/serving.py", line 120, in get_functions_yaml
functions = get_functions()
^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_functions/private/serving.py", line 38, in get_functions
spec.loader.exec_module(module)
File "<frozen importlib._bootstrap_external>", line 940, in exec_module
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/home/runner/work/myapp-web/myapp-web/functions/main.py", line 12, in <module>
db = firestore.client()
^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_admin/firestore.py", line 53, in client
fs_client = _utils.get_app_service(app, _FIRESTORE_ATTRIBUTE, _FirestoreClient.from_app)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_admin/_utils.py", line 98, in get_app_service
return app._get_service(name, initializer) # pylint: disable=protected-access
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_admin/__init__.py", line 295, in _get_service
self._services[name] = initializer(self)
^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_admin/firestore.py", line 69, in from_app
credentials = app.credential.get_credential()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_admin/credentials.py", line 142, in get_credential
self._load_credential()
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_admin/credentials.py", line 159, in _load_credential
self._g_credential, self._project_id = google.auth.default(scopes=_scopes)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/google/auth/_default.py", line 648, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
[2023-06-09T22:15:03.193Z] stderr: 127.0.0.1 - - [09/Jun/2023 22:15:03] "GET /__/functions.yaml HTTP/1.1" 500 -
[2023-06-09T22:15:03.194Z] Got response from /__/functions.yaml <!doctype html>
<html lang=en>
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>
โ functions: Failed to detect functions from source FirebaseError: Failed to parse build specification.
stderr:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:8081
Press CTRL+C to quit
[2023-06-09 22:15:03,188] ERROR in app: Exception on /__/functions.yaml [GET]
Traceback (most recent call last):
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/flask/app.py", line 2190, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/flask/app.py", line 1486, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/flask/app.py", line 1484, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/flask/app.py", line 1469, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_functions/private/serving.py", line 120, in get_functions_yaml
functions = get_functions()
^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_functions/private/serving.py", line 38, in get_functions
spec.loader.exec_module(module)
File "<frozen importlib._bootstrap_external>", line 940, in exec_module
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/home/runner/work/myapp-web/myapp-web/functions/main.py", line 12, in <module>
db = firestore.client()
^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_admin/firestore.py", line 53, in client
fs_client = _utils.get_app_service(app, _FIRESTORE_ATTRIBUTE, _FirestoreClient.from_app)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_admin/_utils.py", line 98, in get_app_service
return app._get_service(name, initializer) # pylint: disable=protected-access
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_admin/__init__.py", line 295, in _get_service
self._services[name] = initializer(self)
^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_admin/firestore.py", line 69, in from_app
credentials = app.credential.get_credential()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_admin/credentials.py", line 142, in get_credential
self._load_credential()
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/firebase_admin/credentials.py", line 159, in _load_credential
self._g_credential, self._project_id = google.auth.default(scopes=_scopes)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/myapp-web/myapp-web/functions/venv/lib/python3.11/site-packages/google/auth/_default.py", line 648, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
127.0.0.1 - - [09/Jun/2023 22:15:03] "GET /__/functions.yaml HTTP/1.1" 500 -
[2023-06-09T22:15:03.[204](https://github.com/myapp-ai/myapp-web/actions/runs/5226451030/jobs/9437127197#step:6:205)Z] stderr: 127.0.0.1 - - [09/Jun/2023 22:15:03] "GET /__/quitquitquit HTTP/1.1" 200 -
Error: Failed to parse build specification:
- FirebaseError Expect manifest yaml to specify a version number
[2023-06-09T22:15:03.[214](https://github.com/myapp-ai/myapp-web/actions/runs/5226451030/jobs/9437127197#step:6:215)Z] stderr: Terminated
Error: Process completed with exit code 1.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.