I just recently set up Firebase functions. After making a simple helloWorld function work, I wanted to set up a cron job following this Google blog tutorial.
I always get an error at this step:
gcloud app deploy app.yaml \ cron.yaml
I get following error message:
C:\Users\vreee\Firebase\functions-cron\appengine>gcloud app deploy app.yaml \
cron.yaml
WARNING: Automatic app detection is deprecated and will soon be removed. As
an alternative, create an app.yaml file yourself using the directions at
https://cloud.google.com/appengine/docs/flexible/python/configuring-your-app-with-app-yaml (App Engine Flexible Environment) or
https://cloud.google.com/appengine/docs/standard/python/config/appref (App
Engine Standard Environment) under the tab for your language.
Deployment to Google App Engine requires an app.yaml file. This
command will run `gcloud beta app gen-config` to generate an app.yaml
file for you in the current directory (if the current directory does
not contain an App Engine service, please answer "no").
Do you want to continue (Y/n)? y
This looks like a Python app. If so, please enter the command to run
the app in production (enter nothing if it's not a python app): :
Writing [app.yaml] to [C:\].
ERROR: gcloud crashed (IOError): [Errno 13] Permission denied:
u'C:\\app.yaml'
If you would like to report this issue, please run the following command:
gcloud feedback
To check gcloud for common problems, please run the following command:
gcloud info --run-diagnostics
Anyone know how to solve this? I searched and set myself with my email address (not a service account) as the owner, so the permission should be there. I just notice that it tried to create an app.yaml file directly under C:\\ instead of the functions-cron folder containing an app.yaml and the cron.yaml file.
Would really appreciate the help!! For additional information, I am using windows..
It seems indeed that the Cloud SDK is trying to create an app.yaml file, which means there was no app.yaml file in your folder C:\Users\vreee\Firebase\functions-cron\appengine. As per the tutorial you linked, both app.yaml and cron.yaml files should be in that directory when you run the deploy command.
So your options are:
If you have already deployed an app and your app.yaml file hasn't changed (i.e it already declares the endpoint for your cron job), you can run the following command from your \functions-cron\appengine folder to upload the cron.yaml file only: gcloud app deploy cron.yaml.
Otherwise, you need to have both files within the same folder and run the command gcloud app deploy app.yaml cron.yaml.
In order for any Google App Engine deployment to work, a configuration file named "App.yaml" is necessary. There is an article in the official documentation about the possible parameters and configurations.
This issue doesn't looks like related to permissions to write in the cloud, but rather permissions to write in your local machine C:. My advice would be that you create the file before the deployment so gcloud doesn't need to be granted admin permissions to write in your local machine.
Related
I've given the service account for the functions the necessary permissions ('Secret Manager Secret Accessor') and when deployed, the firebase functions are able to access the secrets without any problems.
However, when using firebase serve or firebase emulators:start --only functions in local development, I'm getting the following error
Unhandled error Error: 7 PERMISSION_DENIED: Permission 'secretmanager.versions.access' denied for resource
I've found in the documentation that setting export GOOGLE_APPLICATION_CREDENTIALS=pathtoserviceaccount.json is needed to be entered in the terminal, though this did also not work for me.
I would be thankful for all pointers. Cheers.
I've found the answer myself:
When the functions are emulated locally, they do not get run by the App Engine default service account per default, this needs to be enabled as well.
So I had to follow this tutorial https://firebase.google.com/docs/functions/local-shell
The App Engine default service account needs a key which can be created in the Service Accounts settings in the Google Cloud, and then
I had to enter
export GOOGLE_APPLICATION_CREDENTIALS="path/to/key.json"
in the terminal. By running then firebase emulators:start they also got permission to access the Secret Manager.
So while I was on the right track, I was exporting the wrong Service Account key, and not the one that was allowed to run access the Secret Manager.
In order to access Secret Manager from your Firebase application running with local emulator you need to add role of:
"Secret Manager Secret Accessor" to YOUR account used to authenticate with Firebase
You can verify it by running: firebase login in local CLI.
If you're already logged in, it should respond with Already logged in as [email address].
This email address is the Principal account you need to add the role to.
As you've mentioned in your question the "firebase-adminsdk" service account permissions are used on the production deployment, but not on local, unless you specify it with: export GOOGLE_APPLICATION_CREDENTIALS="path/to/key.json"
"[...] you can override secrets values by setting up a .secret.local file. This makes it easy for you to test your functions locally, especially if you don't have access to the secret value."
https://firebase.google.com/docs/functions/config-env#secrets_and_credentials_in_the_emulator
Step by step:
make sure you have the latest version of firebase-tools installed, as this feature is relatively new.
Create a file named secret.local in the root of your firebase project (along side the .firebaserc and firebase.json
add your secrets to the file, formatted the same as way as a regular .env file. e.g.
MY_SECRET_1=foo
MY_SECRET_2=bar
run the emulator firebase emulators:start
within your firebase functions, access the secrets on the process object. e.g. process.env.MY_SECRET_1
note, as far as I can tell, the secrets are only available inside the block scope of a function handler. you can't access them in the root scope of your functions JS code (if somebody finds a way to do that, please comment here as I'd love to know too)
I had the same problem and tried the solution from pureth's answer to adding local overrides, but it didn't work. What did work for me was to create the .secret.local file in the functions directory, not in the project root.
My project structure is as follows:
/
|- .firebaserc
|- firebase.json
|- package.json
|- /* ... */
|- functions/
|- .secret.local
|- package.json
|- /* ... */
So the .secret.local file needs to be placed in the directory where your functions reside and not where the .firebaserc file is.
Also, please note that the file name starts with a dot.
I am trying to deploy my first firebase app. I am getting the message "* You are currently outside your home directory" I googled it and found this reply
"commented on Dec 6, 2016
Just to make sure you're aware. If someone is experiencing the same problem with with the command firebase init
Make the files .firebaserc and firebase.json manually and the deploy should work normally."
I do not know where to create them or what the should contain.
I have also gone to https://www.npmjs.com/package/firebase-tools to try to fix this problem.
If any one can help with this problem I would appreciate it.
If anyone else worried about this just keep going. I continued with the deployment and it deployed OK.
download firebase CLI binary (in case you didn't download it yet. this is an .exe file if you use windows).
copy the downloaded file into your project's root folder (Folder which contains all the files and folders of your projects).
run the firebase-tools-instant-win_2.exe (firebase CLI binary).
a command window will open.
execute all your command in there.
Initialize a Firebase project
Many common tasks performed using the CLI, such as deploying to a Firebase project, require a project directory. You establish a project directory using the firebase init command. A project directory is usually the same directory as your source control root, and after running firebase init, the directory contains a firebase.json configuration file.
To initialize a new Firebase project, run the following command from within your app's directory:
I used firebase init project in my project's directory to get it to work
I am using this tutorial, after I successfully login to Firebase, I need to set the root dir. So as the tutorial instructs, I run:
~/firebase-webchat$ firebase init --public .
However, I get the following error:
error: unknown option `--public'
Does anyone know what command I should be using?
Thanks
I`ve having the same issue, but i finally get a answer for me.
First of all, do you will net logout from your firbase cli login, so lets run:
$ firebase logout
So thats should logout you.
So next lets login again, but at this time, we will need accept the follow question from firebase cli.
$ firebase login --no-localhost
? Allow Firebase to collect anonymous CLI usage information? Yes
If the ask from firebase not appears, just run
$ firebase login --reauth --no-localhost
So before continue, lets make some improvement on our directory structure, put all your files inside directory called "public"
So to the GRAND FINALE, just run
$ firebase init
I hope help you.
Don't use firebase init --public . -> you're probably following the same tutorial I was. Just use firebase init. You'll get asked to set your public directory later.
=== Hosting Setup
Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to be uploaded with firebase deploy. If you
have a build process for your assets, use your build's output directory.
? What do you want to use as your public directory? .
Hope that helped.
After updating Node JS, i was able to deploy the project.
You can try the same by updating Node JS:
sudo npm install npm#latest -g
Not sure but after updating the node.js, i was able to select project from terminal and able to deploy the project using this commands:
firebase deploy
You can set project from terminal too.
firebase deploy -project your-project-id
On deploying my app to Firebase, I am getting this message:
You're seeing this because you've successfully setup Firebase Hosting. Now it's time to go build something extraordinary!
I learnt from a previous post that I need to replace the default index.html with my custom index.html. How do I do that using the Firebase Console?
You cannot change hosted files in the Firebase Console.
Instead, you should change the index.html on your local copy where you initially ran the firebase deploy command. Once you're done with the changes, run firebase deploy again to push the updated version of your website to Firebase Hosting.
For small changes it is probably faster to run firebase serve. This spins up a local web server, so that you can test the changes. Once you're satisfied they work, publish them to Firebase Hosting with firebase deploy again.
Update: this is now possible through some custom scripting. See my answer here for details: Upload single file to firebase hosting via CLI or other without deleting existing ones?
Simply make the changes you want to and then type
npm run build
After this spin the server again using
firebase deploy
The changes you want will be updated.
You can also see the updated changes with the command
firebase serve
and then run firebase deploy when you're satisfied.
First of all Update all the coding and assets files in your local system then,
1) Go to the directory in the terminal by typing $ cd {add your directory}
2) Login on your terminal console by typing $ firebase login in the terminal
3) after login write $ firebase deploy
then, go to Hosting Section in your Firebase Console and delete the previously deployed files by deleting the previously added section in {Poject_Name} release history,
like this
enter image description here
Its a simple solution. This message is caused by the index.html file in your public folder being replaced with the index.html file provided by firebase.
All you have to do is navigate to the directory of your web app folder on your terminal and type in
$ rm .firebaserc
then
$ firebase init
after you've completed the firebase initialization, replace the new index.html file with the one inside the public folder and then type
$ firebase deploy
I am considering using Firebase as MBaaS, however I couldn't find any reliable solution to the following problem:
I would like to set up two separate Firebase environments, one for development and one for production, but I don't want to do a manual copy of features (eg. remote configuration setup, notification rules, etc.) between the development and production environment.
Is there any tool or method I can rely on? Setting up remote configuration or notification rules from scratch can be a daunting task and too risky.
Any suggestions? Is there a better approach than having two separate environments?
Before you post another answer to the question which explains how to set up separate Firebase accounts: it is not the question, read it again. The question is: how to TRANSFER changes between separate dev and prod accounts or any better solution than manually copy between them.
If you are using firebase-tools there is a command firebase use which lets you set up which project you are using for firebase deploy
firebase use --add will bring up a list of your projects, select one and it will ask you for an alias. From there you can firebase use alias and firebase deploy will push to that project.
In my personal use, I have my-app and my-app-dev as projects in the Firebase console.
As everyone has pointed out - you need more than one project/database.
But to answer your question regarding the need to be able to copy settings/data etc from development to production. I had the exact same need. A few months in development and testing, I didn't want to manually copy the data.
My result was to backup the data to a storage bucket, and then restore it from there into the other database. It's a pretty crude way to do it - and I did a whole database backup/restore - but you might be able to look in that direction for a more controlled way. I haven't used it - it's very new - but this might be a solution: NPM Module firestore-export-import
Edit: Firestore backup/export/import info here Cloud Firestore Exporting and Importing Data
If you're using Firebase RTDB, and not Firestore - this documentation might help:
Firebase Automated Backups
You will need to set the permissions correctly to allow your production database access to the same storage bucket as your development.
Good luck.
I'm not currently using Firebase, but considering it like yourself. Looks like the way to go is to create a completely separate project on the console. There was a blogpost up recommending this on the old Firebase site, looks to be removed now though. https://web.archive.org/web/20160310115701/https://www.firebase.com/blog/2015-10-29-managing-development-environments.html
Also this discussion recommending same:
https://groups.google.com/forum/#!msg/firebase-talk/L7ajIJoHPcA/7dsNUTDlyRYJ
The way I did it:
I had 2 projects on firebase- one for DEV other for PROD
Locally my app also had 2 branches - one named DEV, the other named PROD
In my DEV branch I always have JSON file of DEV firebase project & likewise for PROD
This way I am not required to maintain my JSONs.
You will need to manage different build types
Follow this
First, create a new project at Firebase console, name id as YOURAPPNAME-DEV
Click "Add android app" button and create a new app. Name it com.yourapp.debug, for example. New google-services.json file will
be downloaded automatically
Under your project src directory create new directory with name "debug" and copy new google-services.json file here
In your module level build.gradle add this
debug {
applicationIdSuffix ".debug"
}
Now when you build a debug build google-services.json from "debug" folder will be used and when you will build in release mode google-services.json from module root directory will be considered.
I'm updating this answer based on information I just found.
Step 1
In firebase.google.com, create your multiple environments (i.e.; dev, staging, prod)
mysite-dev
mysite-staging
mysite-prod
Step 2
a. Move to the directly you want to be your default (i.e.; dev)
b. Run firebase deploy
c. Once deployed, run firebase use --add
d. An option will come up to select from the different projects you currently have.
Scroll to the project you want to add: mysite-staging, and select it.
e. You'll then be asked for an alias for that project. Enter staging.
Run items a-e again for prod and dev, so that each environment will have an alias
Know which environment you're in
Run firebase use
default (mysite-dev)
* dev (mysite-dev)
staging (mysite-staging)
prod (mysite-dev)
(one of the environments will have an asterisk to the left of it. That's the one you're currently in. It will also be highlighted in blue)
Switch between environments
Run firebase use staging or firebase use prod to move between them.
Once you're in the environment you want, run firebase deploy and your project will deploy there.
Here's a couple helpful links...
CLI Reference
Deploying to multiple environments
Hope this helps.
We chose to fire up instances of the new Firebase emulator on a local dev server for Test and UAT, leaving GCP out of the picture altogether. It's designed exactly for this use-case.
https://firebase.google.com/docs/emulator-suite
This blogpost describes a very simple approach with a debug and release build type.
In a nutshell:
Create a new App on Firebase for each build type using different application id suffix.
Configure your Android project with the latest JSON file.
Using applicationIdSuffix, change the Application Id to match the different Apps on Firebase depending on the build type.
=> see the blogpost for a detailed description.
If you want to use different build flavors, read this extensive blogpost from the official firebase blog. It contains a lot of valuable information.
Hope that helps!
To solve this for my situation I created three Firebase projects, each with the same Android project (i.e. same applicationId without using the applicationIdSuffix suggested by others). This resulted in three google-services.json files which I stored in my Continuous Integration (CI) server as custom environment variables. For each stage of the build (dev/staging/prod), I used the corresponding google-services.json file.
For the Firebase project associated with dev, in its Android project, I added the debug SHA certificate fingerprint. But for staging and prod I just have CI sign the APK.
Here is a stripped-down .gitlab-ci.yml that worked for this setup:
# This is a Gitlab Continuous Integration (CI) Pipeline definition
# Environment variables:
# - variables prefixed CI_ are Gitlab predefined environment variables (https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)
# - variables prefixed GNDR_CI are Gitlab custom environment variables (https://docs.gitlab.com/ee/ci/variables/#creating-a-custom-environment-variable)
#
# We have three Firebase projects (dev, staging, prod) where the same package name is used across all of them but the
# debug signing certificate is only provided for the dev one (later if there are other developers, they can have their
# own Firebase project that's equivalent to the dev one). The staging and prod Firebase projects use real certificate
# signing so we don't need to enter a Debug signing certificate for them. We don't check the google-services.json into
# the repository. Instead it's provided at build time either on the developer's machine or by the Gitlab CI server
# which injects it via custom environment variables. That way the google-services.json can reside in the default
# location, the projects's app directory. The .gitlab-ci.yml is configured to copy the dev, staging, and prod equivalents
# of the google-servies.json file into that default location.
#
# References:
# https://firebase.googleblog.com/2016/08/organizing-your-firebase-enabled-android-app-builds.html
# https://stackoverflow.com/questions/57129588/how-to-setup-firebase-for-multi-stage-release
stages:
- stg_build_dev
- stg_build_staging
- stg_build_prod
jb_build_dev:
stage: stg_build_dev
image: jangrewe/gitlab-ci-android
cache:
key: ${CI_PROJECT_ID}-android
paths:
- .gradle/
script:
- cp ${GNDR_CI_GOOGLE_SERVICES_JSON_DEV_FILE} app/google-services.json
- ./gradlew :app:assembleDebug
artifacts:
paths:
- app/build/outputs/apk/
jb_build_staging:
stage: stg_build_staging
image: jangrewe/gitlab-ci-android
cache:
key: ${CI_PROJECT_ID}-android
paths:
- .gradle/
dependencies: []
script:
- cp ${GNDR_CI_GOOGLE_SERVICES_JSON_STAGING_FILE} app/google-services.json
- ./gradlew :app:assembleDebug
artifacts:
paths:
- app/build/outputs/apk/
jb_build_prod:
stage: stg_build_prod
image: jangrewe/gitlab-ci-android
cache:
key: ${CI_PROJECT_ID}-android
paths:
- .gradle/
dependencies: []
script:
- cp ${GNDR_CI_GOOGLE_SERVICES_JSON_PROD_FILE} app/google-services.json
# GNDR_CI_KEYSTORE_FILE_BASE64_ENCODED created on Mac via:
# base64 --input ~/Desktop/gendr.keystore --output ~/Desktop/keystore_base64_encoded.txt
# Then the contents of keystore_base64_encoded.txt were copied and pasted as a Gitlab custom environment variable
# For more info see http://android.jlelse.eu/android-gitlab-ci-cd-sign-deploy-3ad66a8f24bf
- cat ${GNDR_CI_KEYSTORE_FILE_BASE64_ENCODED} | base64 --decode > gendr.keystore
- ./gradlew :app:assembleRelease
-Pandroid.injected.signing.store.file=$(pwd)/gendr.keystore
-Pandroid.injected.signing.store.password=${GNDR_CI_KEYSTORE_PASSWORD}
-Pandroid.injected.signing.key.alias=${GNDR_CI_KEY_ALIAS}
-Pandroid.injected.signing.key.password=${GNDR_CI_KEY_PASSWORD}
artifacts:
paths:
- app/build/outputs/apk/
I'm happy with this solution because it doesn't rely on build.gradle tricks which I believe are too opaque and thus hard to maintain. For example, when I tried the approaches using applicationIdSuffix and different buildTypes I found that I couldn't get instrumented tests to run or even compile when I tried to switch build types using testBuildType. Android seemed to give special properties to the debug buildType which I couldn't inspect to understand.
Virtuously, CI scrips though are quite transparent and easy to maintain, in my experience. Indeed, the approach I've described worked: When I ran each of the APKs generated by CI on an emulator, the Firebase console's "Run your app to verify installation" step went from
Checking if the app has communicated with our servers. You may need to uninstall and reinstall your app.
to:
Congratulations, you've successfully added Firebase to your app!
for all three apps as I started them one by one in an emulator.
Firebase has a page on this which goes through how to set it up for dev and prod
https://firebase.google.com/docs/functions/config-env
Set environment configuration for your project To store environment
data, you can use the firebase functions:config:set command in the
Firebase CLI. Each key can be namespaced using periods to group
related configuration together. Keep in mind that only lowercase
characters are accepted in keys; uppercase characters are not allowed.
For instance, to store the Client ID and API key for "Some Service",
you might run:
firebase functions:config:set someservice.key="THE API KEY" someservice.id="THE CLIENT ID"
Retrieve current environment configuration To inspect what's currently
stored in environment config for your project, you can use firebase
functions:config:get. It will output JSON something like this:
{
"someservice": {
"key":"THE API KEY",
"id":"THE CLIENT ID"
}
}
Create the Tow project with Dev and production Environment on the firebase
Download the json file from thre
and setup the SDK as per : https://firebase.google.com/docs/android/setup Or for Crashlytics: https://firebase.google.com/docs/crashlytics/get-started?platform=android
First, place the respective google_services.json for each buildType in the following locations:
app/src/debug/google_services.json
app/src/test/google_services.json
app/google_services.json
Note: Root app/google_services.json This file should be there according to the build variants copy the json code in the root json file
Now, let’s whip up some gradle tasks in your: app’s build.gradle to automate moving the appropriate google_services.json to app/google_services.json
copy this in the app/Gradle file
task switchToDebug(type: Copy) {
description = 'Switches to DEBUG google-services.json'
from "src/debug"
include "google-services.json"
into "."
}
task switchToRelease(type: Copy) {
description = 'Switches to RELEASE google-services.json'
from "src/release"
include "google-services.json"
into "."
}
Great — but having to manually run these tasks before you build your app is cumbersome. We would want the appropriate copy task above run sometime before: assembleDebug or :assembleRelease is run. Let’s see what happens when :assembleRelease is run: copy this one in the /gradlew file
Zaks-MBP:my_awesome_application zak$ ./gradlew assembleRelease
Parallel execution is an incubating feature.
.... (other tasks)
:app:processReleaseGoogleServices
....
:app:assembleRelease
Notice the :app:processReleaseGoogleServices task. This task is responsible for processing the root google_services.json file. We want the correct google_services.json to be processed, so we must run our copy task immediately beforehand.
Add this to your build.gradle. Note the afterEvaluate enclosing.
copy this in the app/Gradle file
afterEvaluate {
processDebugGoogleServices.dependsOn switchToDebug
processReleaseGoogleServices.dependsOn switchToRelease
}
Now, anytime :app:processReleaseGoogleServices is called, our newly defined :app:switchToRelease will be called beforehand. Same logic for the debug buildType. You can run :app:assembleRelease and the release version google_services.json will be automatically copied to your app module’s root folder.
The way we are doing it is by creating different json key files for different environments. We have used service account feature as recommended by google and have one development file and another for production