diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 0f1ef76e6c4..80de11f92f6 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -9,8 +9,7 @@ "version": "15.6.0", "license": "MIT", "dependencies": { - "@apphosting/build": "^0.1.6", - "@apphosting/common": "^0.0.8", + "@apphosting/build": "^0.1.7", "@electric-sql/pglite": "^0.3.3", "@electric-sql/pglite-tools": "^0.2.8", "@google-cloud/cloud-sql-connector": "^1.3.3", @@ -301,12 +300,12 @@ } }, "node_modules/@apphosting/build": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@apphosting/build/-/build-0.1.6.tgz", - "integrity": "sha512-nXK1wsR1tehaq9uSRDCGQmN+Dp0xbyGohssYd7g4W8ZbzHfUiab+Pabv34pHVTS03VaSVkjdNcR1g9hezi6s8g==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@apphosting/build/-/build-0.1.7.tgz", + "integrity": "sha512-zNgQGiAWDOj6c+4ylv5ej3nLGXzMAVmzCGMqlbSarHe4bvBmZ2C5GfBRdJksedP7C9pqlwTWpxU5+GSzhJ+nKA==", "license": "Apache-2.0", "dependencies": { - "@apphosting/common": "^0.0.8", + "@apphosting/common": "^0.0.9", "@npmcli/promise-spawn": "^3.0.0", "colorette": "^2.0.20", "commander": "^11.1.0", @@ -327,9 +326,9 @@ } }, "node_modules/@apphosting/common": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@apphosting/common/-/common-0.0.8.tgz", - "integrity": "sha512-RJu5gXs2HYV7+anxpVPpp04oXeuHbV3qn402AdXVlnuYM/uWo7aceqmngpfp6Bi376UzRqGjfpdwFHxuwsEGXQ==", + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@apphosting/common/-/common-0.0.9.tgz", + "integrity": "sha512-ZbPZDcVhEN+8m0sf90PmQN4xWaKmmySnBSKKPaIOD0JvcDsRr509WenFEFlojP++VSxwFZDGG/TYsHs1FMMqpw==", "license": "Apache-2.0" }, "node_modules/@astrojs/compiler": { @@ -22387,11 +22386,11 @@ } }, "@apphosting/build": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@apphosting/build/-/build-0.1.6.tgz", - "integrity": "sha512-nXK1wsR1tehaq9uSRDCGQmN+Dp0xbyGohssYd7g4W8ZbzHfUiab+Pabv34pHVTS03VaSVkjdNcR1g9hezi6s8g==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@apphosting/build/-/build-0.1.7.tgz", + "integrity": "sha512-zNgQGiAWDOj6c+4ylv5ej3nLGXzMAVmzCGMqlbSarHe4bvBmZ2C5GfBRdJksedP7C9pqlwTWpxU5+GSzhJ+nKA==", "requires": { - "@apphosting/common": "^0.0.8", + "@apphosting/common": "^0.0.9", "@npmcli/promise-spawn": "^3.0.0", "colorette": "^2.0.20", "commander": "^11.1.0", @@ -22407,9 +22406,9 @@ } }, "@apphosting/common": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@apphosting/common/-/common-0.0.8.tgz", - "integrity": "sha512-RJu5gXs2HYV7+anxpVPpp04oXeuHbV3qn402AdXVlnuYM/uWo7aceqmngpfp6Bi376UzRqGjfpdwFHxuwsEGXQ==" + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@apphosting/common/-/common-0.0.9.tgz", + "integrity": "sha512-ZbPZDcVhEN+8m0sf90PmQN4xWaKmmySnBSKKPaIOD0JvcDsRr509WenFEFlojP++VSxwFZDGG/TYsHs1FMMqpw==" }, "@astrojs/compiler": { "version": "1.3.1", diff --git a/package.json b/package.json index 70ed901e04a..1ed9ca38646 100644 --- a/package.json +++ b/package.json @@ -104,8 +104,7 @@ ] }, "dependencies": { - "@apphosting/build": "^0.1.6", - "@apphosting/common": "^0.0.8", + "@apphosting/build": "^0.1.7", "@electric-sql/pglite": "^0.3.3", "@electric-sql/pglite-tools": "^0.2.8", "@google-cloud/cloud-sql-connector": "^1.3.3", diff --git a/src/api.ts b/src/api.ts index 85e594cbdd6..6b2c8e5ed86 100755 --- a/src/api.ts +++ b/src/api.ts @@ -38,7 +38,8 @@ export const appDistributionOrigin = () => "https://firebaseappdistribution.googleapis.com", ); export const apphostingOrigin = () => - utils.envOverride("FIREBASE_APPHOSTING_URL", "https://firebaseapphosting.googleapis.com"); + utils.envOverride("FIREBASE_APPHOSTING_URL", "https://staging-firebaseapphosting.sandbox.googleapis.com"); +// firebaseapphosting.googleapis.com"); export const apphostingP4SADomain = () => utils.envOverride( "FIREBASE_APPHOSTING_P4SA_DOMAIN", diff --git a/src/apphosting/backend.ts b/src/apphosting/backend.ts index 9b7d6df0f5e..b7ee054200b 100644 --- a/src/apphosting/backend.ts +++ b/src/apphosting/backend.ts @@ -356,6 +356,7 @@ export async function createBackend( const defaultServiceAccount = defaultComputeServiceAccountEmail(projectId); const backendReqBody: Omit = { servingLocality: "GLOBAL_ACCESS", + runtime: {value: "nodejs22"}, codebase: repository ? { repository: `${repository.name}`, diff --git a/src/deploy/apphosting/deploy.ts b/src/deploy/apphosting/deploy.ts index fa7eaf2bf7a..e9e10567792 100644 --- a/src/deploy/apphosting/deploy.ts +++ b/src/deploy/apphosting/deploy.ts @@ -7,7 +7,7 @@ import { Options } from "../../options"; import { needProjectId } from "../../projectUtils"; import { logLabeledBullet } from "../../utils"; import { Context } from "./args"; -import { createArchive } from "./util"; +import { createArchive, createTarArchive } from "./util"; /** * Zips and uploads App Hosting source code to Google Cloud Storage in preparation for @@ -71,9 +71,9 @@ export default async function (context: Context, options: Options): Promise context.backendLocalBuilds[id]); if (localBuildBackends.length > 0) { - logLabeledWarning( - "apphosting", - `Skipping backend(s) ${localBuildBackends.join(", ")}. Local Builds are not supported yet.`, - ); - backendIds = backendIds.filter((id) => !localBuildBackends.includes(id)); + console.log(localBuildBackends); + console.log(context.backendStorageUris); + console.log(context.backendLocalBuilds); } if (backendIds.length === 0) { @@ -46,16 +44,17 @@ export default async function (context: Context, options: Options): Promise // TODO(9114): Add run_command // TODO(914): Set the buildConfig. - // TODO(914): Set locallyBuiltSource. orchestrateRollout({ projectId, backendId, location: context.backendLocations[backendId], buildInput: { + config: context.backendLocalBuilds[backendId].buildConfig, source: { archive: { userStorageUri: context.backendStorageUris[backendId], rootDirectory: context.backendConfigs[backendId].rootDir, + locallyBuiltSource: true, // generalize }, }, }, diff --git a/src/deploy/apphosting/util.ts b/src/deploy/apphosting/util.ts index 24d2364961e..bffb35c26ae 100644 --- a/src/deploy/apphosting/util.ts +++ b/src/deploy/apphosting/util.ts @@ -1,11 +1,61 @@ import * as archiver from "archiver"; import * as fs from "fs"; import * as path from "path"; +import * as tar from "tar"; import * as tmp from "tmp"; import { FirebaseError } from "../../error"; import { AppHostingSingle } from "../../firebaseConfig"; import * as fsAsync from "../../fsAsync"; +export async function createTarArchive( + config: AppHostingSingle, + rootDir: string, + targetSubDir?: string, +): Promise { + const tmpFile = tmp.fileSync({ prefix: `${config.backendId}-`, postfix: ".tar.gz" }).name; + + const targetDir = targetSubDir ? path.join(rootDir, targetSubDir) : rootDir; + // We must ignore firebase-debug.log or weird things happen if you're in the public dir when you deploy. + // const ignore = config.ignore || [".git"]; + const ignore = ["firebase-debug.log", "firebase-debug.*.log", ".git"]; + //const gitIgnorePatterns = parseGitIgnorePatterns(targetDir); + //ignore.push(...gitIgnorePatterns); + const rdrFiles = await fsAsync.readdirRecursive({ + path: targetDir, + ignore: ignore, + isGitIgnore: true, + }); + const allFiles: string[] = rdrFiles.map((rdrf) => path.relative(rootDir, rdrf.name)); + console.log(allFiles); + + + // `tar` returns a `TypeError` if `allFiles` is empty. Let's check a feww things. + try { + fs.statSync(rootDir); + } catch (err: any) { + if (err.code === "ENOENT") { + throw new FirebaseError(`Could not read directory "${rootDir}"`); + } + throw err; + } + if (!allFiles.length) { + throw new FirebaseError( + `Cannot create a tar archive with 0 files from directory "${rootDir}"`, + ); + } + + await tar.create( + { + gzip: true, + file: tmpFile, + cwd: rootDir, + portable: true, + }, + allFiles, + ); + return tmpFile +} + /** * Locates the source code for a backend and creates an archive to eventually upload to GCS. * Based heavily on functions upload logic in src/deploy/functions/prepareFunctionsUpload.ts. diff --git a/src/gcp/apphosting.ts b/src/gcp/apphosting.ts index 57c02079b0d..2fabe93cf92 100644 --- a/src/gcp/apphosting.ts +++ b/src/gcp/apphosting.ts @@ -7,7 +7,7 @@ import * as deploymentTool from "../deploymentTool"; import { FirebaseError } from "../error"; import { DeepOmit, RecursiveKeyOf, assertImplements } from "../metaprogramming"; -export const API_VERSION = "v1beta"; +export const API_VERSION = "v1alpha"; export const client = new Client({ urlPrefix: apphostingOrigin(), @@ -22,6 +22,10 @@ interface Codebase { rootDirectory: string; } +interface Runtime { + value: string; +} + /** * Specifies how Backend's data is replicated and served. * GLOBAL_ACCESS: Stores and serves content from multiple points-of-presence (POP) @@ -35,6 +39,7 @@ export interface Backend { name: string; mode?: string; codebase?: Codebase; + runtime?: Runtime; servingLocality: ServingLocality; labels: Record; createTime: string;