Workaround for lack of wildcard auth options in Firebase? - firebase

We're using google Cloud Build to deploy pull-request specific versions of our app to GAE so we can share dev versions with stakeholders before launching them into the wild. On GAE, a url looks like http://[VERSION_ID]-dot-[YOUR_PROJECT_ID].appspot.com or https://my-pr-name-dot-projectname.appspot.com
We're want to allow for stakeholders to preview and to run E2E tests (including Firebase login) but because of what's essentially a wildcard subdomain, we'd have to manually whitelist each subdomain in the the Firebase control panel under "Authorized domains" after a deploy. Unfortunately, Firebase doesn't allow for wildcard style whitelisting (eg. *-dot-projectname.appspot.com).
We've reached out to Google support but they've confirmed that whitelisting can only be done manually.

One possibility would be to use a separate, staging project for PR testing.
You'd use whitelisting for http://[YOUR_STAGING_PROJECT_ID].appspot.com or https://staging_projectname.appspot.com. And you'd manage your mapping from a specific PR to the staging project via traffic migrations, which can be done programmatically from your PR automation scripts.
The drawback would be that you'd effectively be verifying only one PR at a time. But that's not necessarily all bad: serializing PR verifications eliminates the risk of breakages due to conflicting changes that each pass in isolation.
There are also advantages of using a separate project for testing purposes you might find of interest, see Advantages of implementing CI/CD environments at GAE project/app level vs service/module level?

We encountered the same issue and decided on authorizing a constant number (say N) of "preview environments". We use GCP cloud run and our CI/CD is ran by github actions. The idea is to iterate through the number of environments such that every N PRs we'll use the same environment, this is done by calculating the modulo of the PR number to N.
Here's the main bash command in the github actions yaml:
run: echo "PREVIEW_ENV=$((${{github.event.number}} % ${{ env.N_PREVIEW_ENVS }}))" >> $GITHUB_ENV

Related

how to automatically deploy to firebase on commit to main branch?

The Main part
I am trying to create a comfortable workflow for myself. I just want to know is there any way to automate deploys from GitHub Repo to Firebase hosting when I commit changes in the repo's main branch at my desktop and push origin to GitHub?
...possibly using "GitHub actions"...
Context and what I've tried
As on 15-Jan-2022 there are two ways I found of deploying website files to firebase hosting.
The de facto firebase cli way, where you use firebase deploy command to push files to firebase hosting.
The automated way using github actions, where the site is deployed automatically every time a pull request is created.
The first one is tedious, the second one is not my cup of cake. Especially because the workflow I want to setup is not too much git oriented, I don't use "pull requests" as far as I understand. I just commit changes directly in the main branch.
(That is so because, I am not a programmer, I just trying to create a blogging site using the Firebase hosting + GitHub repo)
I also referred https://medium.com/firebase-developers/the-comprehensive-guide-to-github-actions-and-firebase-hosting-818502d86c31
Use Deploy to live & preview channels via GitHub pull requests. It will work if you use pull requests to review changes or if you push commits directly to the primary branch.
I would recommend that you use pull requests though. It's a great flow to double check your changes and with the Firebase action it will deploy a temporary preview of the the changes so you can validate everything looks correct.

Firebase RemoteConfig - different configs for different channels

Context:
I'm building a recipe website with Angular frontend and Node.js express backend.
I'm using Heroku for the backend and trying to use Firebase for the frontend. The backend is not ready for use, and is unstable. The frontend is almost ready for v1. For now, all I have is the ability to retrieve a list of recipes from the GET /api/recipes endpoint, and display them (and search through the loaded recipes). Eventually, I plan to add the ability to add/edit/delete/search through the recipes, as well as other endpoints. For now, it works equally well with a static .json file or a dynamic GET endpoint.
In the process of adding this to the backend, the backend will naturally go down and may become temporarily unusable at times, so I'm of course going to have two deployments of the API, and two deployments of the frontend. Prod and Dev, Live and Preview. This should be easy with Heroku, but Firebase is giving me some problems.
I want to have different configs for different deployments. A way for the front-end to ask Firebase "Where's the API I'm supposed to use". This shouldn't go in the repository, code once deploy many, yada: https://12factor.net/codebase . But I haven't figured out how to do this with Firebase.
Goal:
Firebase Remote Config should use a condition such as App Channel to send a different api_url parameter based on what channel the deployment is. This should not be stored in the repository. It should not give away the other deployments etc.
Whatever config I use should be build-once deploy-many. I do not wish to pass a config parameter such as configs:{"recipes.web.app":{apiUrl:"..."}, "recipes-preview-1239j20.web.app":{apiUrl:"..."}}. The frontend must not be aware of other deployments. It shouldn't even really have to be aware of where it's being hosted.
Current Progress:
I successfully deployed different versions to the live channel and the preview channel. I successfully made a RemoteConfig config using GUI (https://console.firebase.google.com/project/<project_name>/config). I did see how to add conditions. I successfully accessed RemoteConfig inside my custom service in Angular. I did find out that init.json on the preview and live channels are identical. I did successfully limit it to "If it's the recipe app", but it's useless because everything's the recipe app. There is a way to make multiple sites, but that's not really useful either, because I'd have to set up the entire app again.
I did not manage to figure out how to deploy remoteconfig.template.json from command line. I did not manage to figure out what conditions are useful. I did not manage to get the "Version" condition to be enabled in the condition selector. I did not manage to find any condition about "channels". I did not manage to find anything with "remote config" and "channels" even on the same page! I did not manage to find anything in firebase docs about "deployments".
Alternative and Unrelated Sidenote:
I'm extremely frustrated with Firebase, and if I can't figure this out, I'm going to abandon it in favor of a Heroku thing I just found. An "unsupported" buildpack for nginx (https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-nginx). "Unsupported" as in it's unofficial. I'm familiar with nginx, and using that will make everything about this personal project (except the server location and build/deploy process) match up with what I'm doing at work. And also both halves of my personal project (static web and api) will be on the same host, which might make things nice.

When configuring CI for a Firebase project, should I use a Firebase token or a GCP service account key?

When configuring CI for a Firebase project, I often see references to either a FIREBASE_TOKEN generated with firebase login:ci or a service account key that (I think) is generated by default for each project.
For my particular use case, I want to do the following:
run online tests (with Firestore) against my test project when running npm run test during my CI build
deploy that code to a different prod project if tests pass
Which one should I use?
I would recommend you to use the FIREBASE_TOKEN. As usually, tokens are better to use, as you can quickly cancel or renew in any issue that you might have it, as well it's easier to manage them a service account and to insert them in the code.
Besides that, the official Firebase documentation - Use the CLI with CI systems - indicates and teaches how to use it with the token, so it seems that indeed, using the token is the best and easier option for you to implement.

Firebase rules and how to test them

I'm working hard on putting up a Firebase backend. In the beginning it is very much straight forward but as the rules grow, it is harder to spot a security flaw. What are the options to actually test the rules? I've looked into Targaryen, which is a 3rd-party library, but can't get it up and running on OSX. Is there a more common approach to test the rules? What is the most common approach to do Firebase security tests?
If you haven't seen it yet, in the Firebase control panel for your app, there's a number of options down the left side; Data, Security and Rules, Simulator; Simulator is the one you want.
Once there, you can authenticate as a user and then test read and write ability on different child nodes.
We crafted our own small app to read/write to different nodes: as our app grew, so did the complexity of the rules and it just made it easier to bang through testing 20 nodes via the app then one at a time in the simulator. Our testing app is all of about 100 lines of code.
I've just set up Bolt and it looks like a much better option than using the standard rules and simulator through the Firebase UI.
You do need to actually use the Bolt syntax but I find it's much easier than the standard rules anyway, especially if they are getting large and complex, since Bolt allows you to create functions to re-use common code for read/write/validate logic. The testing was just a bonus for me.
Introduction to Bolt:
https://www.firebase.com/blog/2015-11-12-security-rules-bolt-user-data.html
Testing instructions: https://github.com/firebase/bolt/issues/80
A few things to note:
The instructions say to install firebase-bolt globally but node can find it unless it's installed locally or you link to the global install.
See this answer to get mocha running. If you add --ui tdd to "test": "mocha --ui tdd" in the scripts section of your package.json file and you keep your tests in test/test.js then you just need to run npm test to run all your tests.
To develop your rules you can use Targaryen.
To test your rules against a live db, you can use the REST api using a token with the debug flag set to true (database secret used to create those token are deprecated but I don't think you create such token with the new Firebase Admin SDK); the response header will include debug info about rule evaluation.
To debug your rules and production data use the simulator in the firebase console (note that it doesn't allow to simulate update operation AFAIK)

Choose which configurations to build in Jenkins multi-configuration job

We're using Jenkins to build an ASP.Net web application and deploying successful builds to stage/test server. The application has multiple configurations (different connnectionstrings, themes, etc) to adapt to different customers.
So, using a multi-configuration job was the natural way to go. This works great for building and deploying all configurations in one go. But what if you only want to build one or a couple of the configurations?
Typical scenario when this would be nice:
The developer completes a milestone/version, test phase starts and 10 configurations are built and deployed on the stage server
Test team identifies a bug in configuration X (i.e. customer X)
The developers fixes the bug (or so they believe) and want the code re-tested
Run the Jenkins job again to get the code on to the stage server
This scenario builds ~9 configurations for nothing. And while these 9 configurations are deployed, anyone who is logged in on one of these test web sites are of course loosing their sessions.
We would like have some parameter that let's us select which configurations to build.
A couple of potential solutions:
The Matrix Reloaded Plugin which should let you rebuild only certain configurations.
Alternatively, when you configure the job, you can enable the "Combination Filter" feature, which tells Jenkins which combinations of the matrix axes to build. However this isn't very dynamic — i.e. you can't change this each time you build. Though maybe it's possible to parameterise this field (I haven't tried this).

Resources