@@ -18,6 +18,7 @@ import {
1818 eventarcOrigin ,
1919 pubsubOrigin ,
2020 storageOrigin ,
21+ secretManagerOrigin ,
2122} from "../../api" ;
2223import { Options } from "../../options" ;
2324import {
@@ -205,6 +206,7 @@ export async function prepare(
205206 `preparing ${ clc . bold ( sourceDirName ) } directory for uploading...` ,
206207 ) ;
207208 }
209+
208210 if ( backend . someEndpoint ( wantBackend , ( e ) => e . platform === "gcfv2" ) ) {
209211 const packagedSource = await prepareFunctionsUpload ( sourceDir , config ) ;
210212 source . functionsSourceV2 = packagedSource ?. pathToSource ;
@@ -241,34 +243,9 @@ export async function prepare(
241243 const wantBackend = backend . merge ( ...Object . values ( wantBackends ) ) ;
242244 const haveBackend = backend . merge ( ...Object . values ( haveBackends ) ) ;
243245
246+ await ensureAllRequiredAPIsEnabled ( projectNumber , wantBackend ) ;
244247 await warnIfNewGenkitFunctionIsMissingSecrets ( wantBackend , haveBackend , options ) ;
245248
246- // Enable required APIs. This may come implicitly from triggers (e.g. scheduled triggers
247- // require cloudscheudler and, in v1, require pub/sub), or can eventually come from
248- // explicit dependencies.
249- await Promise . all (
250- Object . values ( wantBackend . requiredAPIs ) . map ( ( { api } ) => {
251- return ensureApiEnabled . ensure ( projectId , api , "functions" , /* silent=*/ false ) ;
252- } ) ,
253- ) ;
254- if ( backend . someEndpoint ( wantBackend , ( e ) => e . platform === "gcfv2" ) ) {
255- // Note: Some of these are premium APIs that require billing to be enabled.
256- // We'd eventually have to add special error handling for billing APIs, but
257- // enableCloudBuild is called above and has this special casing already.
258- const V2_APIS = [ cloudRunApiOrigin ( ) , eventarcOrigin ( ) , pubsubOrigin ( ) , storageOrigin ( ) ] ;
259- const enablements = V2_APIS . map ( ( api ) => {
260- return ensureApiEnabled . ensure ( context . projectId , api , "functions" ) ;
261- } ) ;
262- await Promise . all ( enablements ) ;
263- // Need to manually kick off the p4sa activation of services
264- // that we use with IAM roles assignment.
265- const services = [ "pubsub.googleapis.com" , "eventarc.googleapis.com" ] ;
266- const generateServiceAccounts = services . map ( ( service ) => {
267- return generateServiceIdentity ( projectNumber , service , "functions" ) ;
268- } ) ;
269- await Promise . all ( generateServiceAccounts ) ;
270- }
271-
272249 // ===Phase 6. Ask for user prompts for things might warrant user attentions.
273250 // We limit the scope endpoints being deployed.
274251 const matchingBackend = backend . matchingBackend ( wantBackend , ( endpoint ) => {
@@ -533,3 +510,48 @@ export async function warnIfNewGenkitFunctionIsMissingSecrets(
533510 }
534511 }
535512}
513+
514+ // Enable required APIs. This may come implicitly from triggers (e.g. scheduled triggers
515+ // require cloudscheduler and, in v1, require pub/sub), use of features (secrets), or explicit dependencies.
516+ export async function ensureAllRequiredAPIsEnabled (
517+ projectNumber : string ,
518+ wantBackend : backend . Backend ,
519+ ) : Promise < void > {
520+ await Promise . all (
521+ Object . values ( wantBackend . requiredAPIs ) . map ( ( { api } ) => {
522+ return ensureApiEnabled . ensure ( projectNumber , api , "functions" , /* silent=*/ false ) ;
523+ } ) ,
524+ ) ;
525+ if ( backend . someEndpoint ( wantBackend , ( e ) => e . platform === "gcfv2" ) ) {
526+ // Note: Some of these are premium APIs that require billing to be enabled.
527+ // We'd eventually have to add special error handling for billing APIs, but
528+ // enableCloudBuild is called above and has this special casing already.
529+ const V2_APIS = [ cloudRunApiOrigin ( ) , eventarcOrigin ( ) , pubsubOrigin ( ) , storageOrigin ( ) ] ;
530+ const enablements = V2_APIS . map ( ( api ) => {
531+ return ensureApiEnabled . ensure ( projectNumber , api , "functions" ) ;
532+ } ) ;
533+ await Promise . all ( enablements ) ;
534+ // Need to manually kick off the p4sa activation of services
535+ // that we use with IAM roles assignment.
536+ const services = [ "pubsub.googleapis.com" , "eventarc.googleapis.com" ] ;
537+ const generateServiceAccounts = services . map ( ( service ) => {
538+ return generateServiceIdentity ( projectNumber , service , "functions" ) ;
539+ } ) ;
540+ await Promise . all ( generateServiceAccounts ) ;
541+ }
542+
543+ // If function is making use of secrets, go ahead and enable Secret Manager API.
544+ if (
545+ backend . someEndpoint (
546+ wantBackend ,
547+ ( e ) => ! ! ( e . secretEnvironmentVariables && e . secretEnvironmentVariables . length > 0 ) ,
548+ )
549+ ) {
550+ await ensureApiEnabled . ensure (
551+ projectNumber ,
552+ secretManagerOrigin ( ) ,
553+ "functions" ,
554+ /* silent=*/ false ,
555+ ) ;
556+ }
557+ }
0 commit comments