action-hosting-deploy
action-hosting-deploy copied to clipboard
Support Preview Deployments with Hosting rewrites to Cloud Functions
The use case you're trying to solve
Deploy SSR web apps with Preview Deployments.
Current solutions require an entire separate project for dev and prod with dev being shared amongst developers, or relying solely on local emulation which is not quite as robust as a full env deployment.
Change to the action that would solve that use case
There would need to be a new Cloud Function for the Preview Deployment (PR prefix etc) with the rewrite config updated on deployment for the Hosting Preview Channel.
Other considerations
I believe I requested this feature about a year ago, perhaps in the Google Group, but have seen no update.
Additional info
I have written about SSR web apps on Firebase with various frameworks and authored the Firebase adapter for SvelteKit.
It's a pity that there is no easy way on how to do previews with the SSR function.
Is this a limitation of firebase preview itself that it doesn't support functions with rewrites for preview hosting? Is there a feature request for this somewhere or should we create one?
The preview website uses the same firebase.json:hosting.* config so I believe rewrites still work, just they all point to the same Cloud Function.
I could be wrong, but assuming not, this is what would need to change:
The deployment of a preview site would need to check if it relies on hosting.rewrites.function and if so, deploy a copy of function X with the --CHANNEL_ID-RANDOM_HASH suffix and then modify the rewrite rule to use the that copy function name.
EG:
This would be my configuration:
{
"hosting": [
{
"site": "site1",
"public": "cdn",
"cleanUrls": true,
"rewrites": [
{
"source": "**",
"function": "mySSR"
}
],
"predeploy": []
}
],
"functions": {
"source": "functions",
},
}
// functions/index.js
exports.mySSR = functions.https.onRequest(async (request, response) => {});
This would be what the preview process deploys:
{
"hosting": [
{
"site": "site1--CHANNEL_ID-RANDOM_HASH",
"public": "cdn",
"cleanUrls": true,
"rewrites": [
{
"source": "**",
"function": "mySSR--CHANNEL_ID-RANDOM_HASH"
}
],
"predeploy": []
}
],
"functions": {
"source": "functions",
},
}
// functions/index.js
exports.mySSR = functions.https.onRequest(async (request, response) => {});
exports.mySSR--CHANNEL_ID-RANDOM_HASH = mySSR;
And then when the preview channel is destroyed it removes mySSR--CHANNEL_ID-RANDOM_HASH
Even better would be if for each preview channel we got our entire functions/index.js wrapped in a Function Group with the CHANNEL_ID-RANDOM_HASH resulting in copies of all our functions
- id: auth name: Authenticate to Google Cloud uses: google-github-actions/[email protected] with: - uses: FirebaseExtended/action-hosting-deploy@v0 with: repoToken: "${{ secrets.GITHUB_TOKEN }}" firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_LAWVITE_DEV }}" expires: 20d projectId: lawvite create_credentials_file: true workload_identity_provider: ... service_account: ${{ secrets.SERVICE_ACCOUNT_EMAIL }}
- name: 🚀 Firebase Deploy uses: FirebaseExtended/action-hosting-deploy@v0 with: repoToken: '${{ secrets.GITHUB_TOKEN }}' credentials_file_path: ${{ steps.auth.output.credentials_file_path }} projectId: '${{ secrets.PROJECT_ID }}' channelId: live env: FIREBASE_CLI_PREVIEWS: hostingchannels
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: "${{ secrets.GITHUB_TOKEN }}"
firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_LAWVITE_DEV }}"
expires: 20d
projectId: lawvite
package-lock.json
What I do is provide an SSR-free version for preview, only deploy SSR on main branch
First I create a new firebase.preview.json for preview environment, which provides only client-side rendering
// firebase.preview.json
{
"hosting": {
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
// ...
}
}
Keep your SSR settings in the old firebase.json:
// firebase.json
{
"hosting": {
"rewrites": [
{
"source": "**",
"function": "ssr"
}
]
},
"functions": {
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint"
]
}
// ...
}
and overwrite firebase.json with it when building preview channels
name: Deploy to Firebase Hosting on PR
'on': pull_request
jobs:
build_and_preview_dev:
if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}'
runs-on: ubuntu-latest
steps:
- run: npm ci && cp ./firebase.preview.json ./firebase.json && FIREBASE_ENV=development npm run build
- ...
Though I can't preview SSR results in preview channels, but this prevents rendering wrong result an bundles in preview channels.