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.
Related
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.
The Issue
I am currently in the process of integrating a pre-rendering service for SEO optimization, however we use an Azure App Service Plan to scale up or down when necessary.
One of the steps for setting up the proper configuration requires placing an applicationHost.xdt file in the /site/ directory, which is one level above the /site/wwwroot directory where the application itself gets deployed to.
What steps should I take in order to have the applicationHost.xdt file persist to new instances spawned by the scaling process?
Steps I have taken to solve the issue
So far I have been Googling a lot, but haven't succeeded in finding a lot of documentation on using an applicationHost.xdt file in combination with an Azure App Service Plan.
I am able to upload the file to an instance manually, however I have assumed that when we then scale up to more instances the manually uploaded file will not be present on the new instance(s).
Etcetera
We are using Prerender.io as pre-rendering service.
Should there be an easier to set-up & similarly priced service available, we would be open to suggestions as we are in an exploratory phase regarding pre-rendering.
Suppose this won't be a problem, cause all files under azure app are shared between all your instances. You could check it in this Kudu wiki:Persisted files. And in my test all instances will keep the file.
About upload the applicationHost.xdt, you don't have to do it manually, there is a IIS Manager Site Extension to lets you very easily create XDT files. And it will provide some sample XDT's for you.
I have an open-source project that uses two separate Firebase projects for a test environment and the production one.
Ultimately, I want to have other developers be able to pull down the project and actually be able to run it WITHOUT me needing to give each individual developer access.
I see a number of solutions in this question: How to add collaborators to a Firebase app?. Those all seem to require each person's email.
I understand why it maybe isn't a thing, but I am wondering if there is a way to just give access to everyone for only the test project so that contributing is super low-friction. Something similar to Firestore database rules that allow read/write in a public fashion to get started for testing.
I've tried making a new IAM account in the Google Cloud Console, and I think that partially worked for the Firebase Cloud Functions access to Admin SDK, but my collaborators get hung up trying to run firebase use <test-firebase-project> saying that they don't have access.
I see a lot of other config options for IAM, but nothing sticking out to me for this public access scenario.
Can anyone confirm this either is or isn't a thing?
Thanks!
EDIT
To add some more detail to my project...
I am using Authentication, Firestore, and Cloud Functions. The only js package I will use is the Auth one, which will be loaded from a CDN (so I believe that doesn't apply to my question).
I want to give access to people to run the Cloud Functions locally. There is a pre-build step that I have made in vanilla Node that calls a Cloud Function (running locally), which uses the Firebase Admin SDK to call my Firestore database. I then write that response to a JSON file that my front end uses.
When my collaborators pull down the project, and install the Firebase CLI, when they try to serve the Cloud Functions locally, they get hit with a "no access" type of error. I was trying to resolve this by adding a service account into the /functions directory, but apparently that didn't help.
My collaborators don't need access to the console at all. I basically just need them to be able to run the Cloud Function locally (and make sure they can't access my production Firebase project).
I am happy to add more detail, but I kind of feel like I am just rambling. Thanks again.
There is no way to grant everyone contributor access to your Firebase console. You will either have add each individual user, or create your own dashboard that uses the API to show the relevant data.
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
I am working on a ASP.net MVC4 project where a same project needs to be deployed to many clients on daily basis, each client will have its own domain / sub domain and a separate app pool and db (MSSSQL).
Doing each deployment manually could take at least 1-2 hours if everything goes well. Is there anyway using which I can do this in some automated way?
Moreover, we also need to update all of the apps when a new version is released.. may be one by one or all of them at same time. However, doing this manually could take weeks and once we have more clients then it will not possible doing this update manually.
The update involves, suspending app for some time, taking a full backup of files and db, update application code/ files in app folder, upgrade db with a script and then start app, doing some diagnosis script to check if update was successful or not, if not we need to check what went wrong?
How can we automate this updates? Any idea would be great on how to approach this issue.
As a developer for BuildMaster, I can say that this scenario, known as the "Core Version" pattern, is a common one. If you're OK with a paid solution, you can setup your deployment plans within the tool that do exactly what you described.
As a more concrete example, we experience this exact situation in a slightly different way. BuildMaster has a set of 60+ extensions that rely on a specific SDK version. In our recent 4.0 release, we had to re-deploy every extension because of breaking API changes within the SDK. This is essentially equivalent to having a bunch of customers and deploying to them all at once. We have set up our deployment plans such that any time we create a new release of the SDK application, we have the option to set a variable that says to build every extension that relies on the SDK:
In BuildMaster, the idea is to promote a build (i.e. an immutable object that travels through various environments like Dev, Test, Staging, Prod) to its final environment (where it becomes the deployed build for the release). In your case, this would be pushing your MVC application to its final environment, and that would then trigger the deployments of all dependent applications (i.e. your customers' instances of your application). For our SDK, the plan looks like this:
For your scenario, you would only need the single action, "Promote Build". As I mentioned before, any dependents would then be promoted to their final environments, so all your customer deployments would kick off once that action is run during deployment. As an example, our Azure extension's deployment plan for its final environment looks like this (internal URLs redacted):
You may have noticed that these plans are marked "Shared", which means every extension we have has the exact same deployment plan, but utilizes different variables to handle the minor differences like names, paths, etc.
Since this is such an enormous topic I could go on for ages, but I think that should be sufficient for your use-case if you wanted to try it out.
There are others but you could setup Team Server Foundation to deploy automated builds.
http://msdn.microsoft.com/en-us/library/ff650529.aspx
I find the easiest way to do this from an MVC project is to create a publish profile.
This is done by right-clicking your project selecting publish and then configuring it to your needs.
Then from TFS you create a new build definition, this kicks of a wizard which takes you through it.
There are quite a few options which would be too long to go into for every scenario.
The main change I usually find the most important is to set an MSBuild Argument to deploy with the publish profile.
This can be found at Process > Advanced > MSBuild Arguments.
Once this is configured correctly it's a simple case of right-clicking and queue new build to build and deploy.
You wil need different PublishProfile/Build configuration per deployment environment.
For backups I use a powershell script which can be called manually or from TFS.
You also have a drop folder in TFS which keeps a backup of x many releases.
The datbases are automatically configured via Sql server to backup, TBH I didn't set that up it was a DB admin guy who is also involved with releases.
From a dev testing side I use jMeter (http://jmeter.apache.org/) to run some automated scripts that check that users can login and view certain screens, just to confirm nothing major has gone wrong. However there is usually a testing team to run more detailed tests, again not setup by me.
All of the above will probably take you sometime to setup but in the long run it will literally save you weeks of time over a year.
A free alternative to TFS is http://www.cruisecontrolnet.org/, I have used this in the past too and is pretty good.
You can automate your .Net deployments with Beanstalk, which will give you a way to trigger deployments with a single click, watch progress, manage permissions and see history of deployments. Check out this guide on the topic:
http://guides.beanstalkapp.com/deployments/deploy-dotnet.html
I hope you will find it useful.
P.S. - I work at Beanstalk.