firebase / firebase-tools

The Firebase Command Line Tools
MIT License
3.98k stars 918 forks source link

Unable to deploy function with service account parameter #5224

Open taeold opened 1 year ago

taeold commented 1 year ago
    Hi @inlined ,

I'm trying using parameterized codebases but I have this failure :

[2022-11-07T10:54:51.173Z] Got response from /__/functions.yaml Failed to generate manifest from function source: TypeError: serviceAccount.includes is not a function
[2022-11-07T10:54:51.177Z] Failed to parse functions.yamlincomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line at line 1, column 60:
     ...  from function source: TypeError: serviceAccount.includes is not ... 
                                         ^ {"name":"YAMLException","reason":"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line","mark":{"name":null,"buffer":"Failed to generate manifest from function source: TypeError: serviceAccount.includes is not a function\n\u0000","position":59,"line":0,"column":59},"message":"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line at line 1, column 60:\n     ...  from function source: TypeError: serviceAccount.includes is not ... \n                                         ^"}
[2022-11-07T10:54:51.181Z] shutdown requested via /__/quitquitquit

Error: Failed to load function definition from source: Failed to generate manifest from function source: TypeError: serviceAccount.includes is not a function
Error: Process completed with exit code 1.

In my code, I have this :

const {defineString} = require("firebase-functions/params");

const configuration = {
   ...,
   runtimeOptions: {
        serviceAccount: defineString("CF_SERVICE_ACCOUNT", {default: "default"}),
   }
}

The CF_SERVICE_ACCOUNT is configured in my functions/.env.[default|preproduction|production] like this : CF_SERVICE_ACCOUNT=cloud-functions-runner@<PROJECT_ID>.iam.gserviceaccount.com

Do you have an idea where I made a mistake ?

I upgraded to the latest Firebase tools CLI : 11.16.0

Originally posted by @fgruchala in https://github.com/firebase/firebase-functions/issues/1275#issuecomment-1305435951

fgruchala commented 1 year ago

Thanks @taeold 👍🏻 for creating this new issue

IchordeDionysos commented 1 year ago

@taeold In general, I would have expected to configure all config via params...

For us, this is a blocking feature, as we no longer can supply the service account with the prefix: serviceAccount@, which depending on the project, would either resolve to serviceAccount@prod-project... or serviceAccount@stage-project...

fgruchala commented 1 year ago

@taeold do you have some visibility about this issue ?

taeold commented 1 year ago

@fgruchala Sorry for the silence. We are actively working on getting service account parametrizable and going through internal process to get the API approved. Will keep you all posted.

fgruchala commented 1 year ago

@taeold @Berlioz do you have any information ?

taeold commented 1 year ago

WIP https://github.com/firebase/firebase-tools/pull/5234

fgruchala commented 1 year ago

WIP https://github.com/firebase/firebase-tools/pull/5234

Huge thanks

Hibrix-net commented 1 year ago

Any news here? I'm also unable to parameterize serviceAccount within runWith ...

IchordeDionysos commented 1 year ago

@taeold is something similar planned for the function region?

stfsy commented 11 months ago

@Hibrix-net @fgruchala I faced the same challenge.

For now, I resorted to using the GCLOUD_PROJECT env var to construct the actual service account name at deployment time. Of course, this is only a possible solutions if the service accounts have the same name.

import { defineString } from 'firebase-functions/params';
import { setGlobalOptions } from 'firebase-functions/v2/options';

const gcpCloudRegionParam = defineString("DSQ_GCP_CLOUD_REGION")

setGlobalOptions({
    region: [gcpCloudRegionParam],
    serviceAccount: `cloud-run-functions@${process.env.GCLOUD_PROJECT}.iam.gserviceaccount.com`
})
IchordeDionysos commented 11 months ago

Do you know if this is fixed now? I remember a PR from @taeold about it in the past, if I'm not mistaken.

stfsy commented 11 months ago

@IchordeDionysos not fixed. I just tried a few days ago and it didn't work.

IchordeDionysos commented 11 months ago

@stfsy but you can supply an Expression no? 🤔 https://github.com/firebase/firebase-functions/blob/master/src/v2/providers/https.ts#L141

Are you using functions v1 or v2?

stfsy commented 11 months ago

@IchordeDionysos yeah but an expression is not a param, I guess.

I wrote a blog post about the issue yesterday: https://medium.com/@stfsy/different-service-accounts-for-firebase-functions-per-stage-e667db4059e4. Gist is the serviceAccount parameter does not get resolved, but merely copied as is: https://github.com/firebase/firebase-tools/blob/eea3e2256121ab2648a764d007222e88b86de344/src/deploy/functions/build.ts#L455-L462

Thus, when passing a param instead of a string value, the param expression will be used and not the value that could be.

You can see in branch that was created for the PR this line was added to actually resolve the value of the serviceAccount param https://github.com/firebase/firebase-tools/blob/568c7a1593715e92d2b549125a09b36108bc698c/src/deploy/functions/build.ts#L451-L458

I added this line to the current firebase-tools version and it works pretty fine. The whole refactoring that was started for the serviceAccount param is not really necessary to fix this issue in my opinion.

I am using v2 functions.