Open TomDarmon opened 5 months ago
Optional, but if you need to see every steps as one big script I've made github actions for my CD. This might give a global overview of the steps to follow:
backend-cd.yml
name: Deploy to Cloud Run on merge
on:
push:
branches:
- main
jobs:
build_and_deploy_backend:
runs-on: ubuntu-latest
env:
# Env variables
GCP_PROJECT_ID: ${{ vars.GCP_PROJECT_ID }}
WASP_SERVER_URL_DEV: ${{ vars.WASP_SERVER_URL_DEV }}
WASP_WEB_CLIENT_URL_DEV: ${{ vars.WASP_WEB_CLIENT_URL_DEV }}
ADMIN_EMAILS_DEV: ${{ vars.ADMIN_EMAILS_DEV }}
# Secrets
DATABASE_URL_DEV: ${{ secrets.DATABASE_URL_DEV }}
SERVICE_ACCOUNT: ${{ secrets.SERVICE_ACCOUNT }}
GOOGLE_CLIENT_ID_DEV: ${{ secrets.GOOGLE_CLIENT_ID_DEV }}
GOOGLE_CLIENT_SECRET_DEV: ${{ secrets.GOOGLE_CLIENT_SECRET_DEV }}
HOBBY_SUBSCRIPTION_PRICE_ID_DEV: ${{ secrets.HOBBY_SUBSCRIPTION_PRICE_ID_DEV }}
PRO_SUBSCRIPTION_PRICE_ID_DEV: ${{ secrets.PRO_SUBSCRIPTION_PRICE_ID_DEV }}
SENDGRID_API_KEY_DEV: ${{ secrets.SENDGRID_API_KEY_DEV }}
STRIPE_KEY_DEV: ${{ secrets.STRIPE_KEY_DEV }}
STRIPE_WEBHOOK_SECRET_DEV: ${{ secrets.STRIPE_WEBHOOK_SECRET_DEV }}
JWT_SECRET_DEV: ${{ secrets.JWT_SECRET}}
steps:
- uses: actions/checkout@v4
- name: Build Docker Image
run: |
curl -sSL https://get.wasp-lang.dev/installer.sh | sh
cd app
wasp build
cd .wasp/build
docker build -t backend-image -f Dockerfile .
docker tag backend-image europe-west1-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/backend/backend-image:${{ github.sha }}
- name: Authenticate to GCP
uses: google-github-actions/auth@v1
with:
credentials_json: ${{ secrets.SERVICE_ACCOUNT }}
- name: Configure Docker
run: |
gcloud auth configure-docker europe-west1-docker.pkg.dev
- name: Push Docker Image
run: |
docker push europe-west1-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/backend/backend-image:${{ github.sha }}
- name: Deploy to Cloud Run
run: |
gcloud run deploy backend \
--image europe-west1-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/backend/backend-image:${{ github.sha }} \
--project ${{ env.GCP_PROJECT_ID }} \
--platform managed \
--region europe-west1 \
--max-instances 2 \
--min-instances 0 \
--allow-unauthenticated \
--set-env-vars "DATABASE_URL=${{ env.DATABASE_URL_DEV }}" \
--set-env-vars "STRIPE_KEY=${{ env.STRIPE_KEY_DEV }}" \
--set-env-vars "GOOGLE_CLIENT_ID=${{ env.GOOGLE_CLIENT_ID_DEV }}" \
--set-env-vars "GOOGLE_CLIENT_SECRET=${{ env.GOOGLE_CLIENT_SECRET_DEV }}" \
--set-env-vars "HOBBY_SUBSCRIPTION_PRICE_ID=${{ env.HOBBY_SUBSCRIPTION_PRICE_ID_DEV }}" \
--set-env-vars "PRO_SUBSCRIPTION_PRICE_ID=${{ env.PRO_SUBSCRIPTION_PRICE_ID_DEV }}" \
--set-env-vars "SENDGRID_API_KEY=${{ env.SENDGRID_API_KEY_DEV }}" \
--set-env-vars "STRIPE_WEBHOOK_SECRET=${{ env.STRIPE_WEBHOOK_SECRET_DEV }}" \
--set-env-vars "WASP_SERVER_URL=${{ env.WASP_SERVER_URL_DEV }}" \
--set-env-vars "WASP_WEB_CLIENT_URL=${{ env.WASP_WEB_CLIENT_URL_DEV }}" \
--set-env-vars "ADMIN_EMAILS=${{ env.ADMIN_EMAILS_DEV }}" \
--set-env-vars "JWT_SECRET=${{ env.JWT_SECRET_DEV }}"
frontend-cd.yml
name: Deploy to Firebase Hosting on merge
on:
push:
branches:
- main
jobs:
build_and_deploy_frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
curl -sSL https://get.wasp-lang.dev/installer.sh | sh
cd app
wasp build
cd .wasp/build/web-app
npm install
REACT_APP_API_URL=${{ vars.WASP_SERVER_URL_DEV }}
npm run build
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: ${{ secrets.GITHUB_TOKEN }}
firebaseServiceAccount: ${{ secrets.SERVICE_ACCOUNT }}
channelId: live
projectId: ${{ vars.GCP_PROJECT_ID }}
This is awesome, thanks @TomDarmon !
We can use this as a good foundation for writing the docs for deploying to GCP.
CI action is also quite useful!
The backend URL is a bit ugly, additionally it is not under the same domain so you might run under CORS issues. Firebase offers automatic redirect to the cloud run backend directly from your website, I still need to crack that part !
While Firebase does offer a way to rewrite routes to send all requests to e.g. example.com/api
towards the server, we concluded that better option is, if we do want to have server on the same domain as the client, to go with a subdomain instead (e.g. api.example.com
) as it provides multiple benefits and is easier to set up (DNS configuration + a bit of config on the GCP side).
Related convo on the Discord: https://discord.com/channels/686873244791210014/1249887793082138758/1249887793082138758
Is this just for the hosting? I am currently trying to link up an existing project that uses firebase as DB to use open-saas to add payments, but there doesnt seem to be an easy way to replace the prism stuff with firebase.
@avetise yes correct, it says above firebase is used for static hosting. I can update the github issue to make that clearer.
Using firebase instead of Prisma -> Wasp is currently heavly relying on Prisma, and while you can use firebase on the side as additional db, replacing Prisma with Firebase at this point wouldn't make much sense I think.
Hello, I've recently gone through the steps to deploy open-saas on GCP and I believe it could be useful to document it here for now.
This could be added to the real documentation in the future, for now I'll just detail what I did to make it work.
A few prerequisites: • Have a GCP account & project with billing enabled (you might succeed without, but that's what I had). • Successfully run the open-saas template locally with, the appropriate env variable and an emailSender not set to Dummy.
Step 1 - GCP & firebase setup:
First, login to GCP and populate the default credentials. This step is important, it will ensure you don't get access issues. Run the 2 command separately and login each time:
gcloud auth login
gcloud auth application-default login
In your GCP project, enable the needed APIs:
We will be building our Docker image and storing it in GCP, therefore we need to create an artifact registry where we will push the image:
For the firebase setup:
Step 2 - Deploy the frontend with firebase hosting
Follow the step 1 and 3 to get the build of the frontend (give a fake REACT_APP_API_URL for now, since we don't have it yet) --> https://wasp-lang.dev/docs/0.11.8/advanced/deployment/manually#1-generating-deployable-code
Add this firebase.json and .firebashrc at the root of your repo, optionally you can put them elsewhere but you need to adapt the paths and where you will run the firebase commands:
firebase.json
.firebaserc
Now you are ready to deploy the frontend:
npm install -g firebase-tools
firebase login
firebase deploy --only hosting
--> Do this from the root of the repo if you did place the firebase.json at root and didn't change any pathStep 3 - Deploy the backend with cloud run
Cloud run expects the container service to be exposed on port 8080, this cannot be changed. So we need to find a way to do this, luckily the wasp team enabled us to overwrite the Dockerfile server entry point and add any steps ! See the doc --> https://wasp-lang.dev/docs/advanced/deployment/overview#customizing-the-dockerfile
Create a Dockerfile at ./app/Dockerfile
Now you need to do a
wasp build
again with this setup to update the Dockerfile under .wasp/build/Dockerfile. After the wasp build command, you can check that the new Dockerfile has indeed your added steps in it.Build the image and push it to Artifact Registry. I will use the Docker Artifact Registry I created in step 1 but adapt it to the one you created:
Once the image is successfully uploaded to artifact registry, you can deploy your backlend with:
You will receive a made up backend URL, for example
https://backend-feiufeaoa-ew.a.run.app
Step 4 - Link the frontend and backend
You now have all the elements, you just need to piece it together:
REACT_APP_API_URL
set to your backend URL (https://backend-feiufeaoa-ew.a.run.app)WASP_SERVER_URL
env variable of your backend to the real one (https://backend-feiufeaoa-ew.a.run.app)You can go back to your frontend under https://{FILL_YOUR_FULL__GCP_PROJECT_NAME}.web.app and check that everything works.
The backend URL is a bit ugly, additionally it is not under the same domain so you might run under CORS issues. Firebase offers automatic redirect to the cloud run backend directly from your website, I still need to crack that part !