-
Notifications
You must be signed in to change notification settings - Fork 162
Separate adapter builds into helper function. #384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @annajowang, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request significantly refactors the build process for apphosting framework adapters. It extracts the core logic for fetching and executing framework-specific builds into a dedicated, reusable helper function. This helper is then integrated into the localbuild.ts
script, which is updated to accept a framework argument, making the build process more modular and extensible. Additionally, a list of supported frameworks is introduced to ensure valid inputs.
Highlights
- Introduction of
adapterBuild
Helper Function: A new file,adapter-builds.ts
, has been added. It exports an asynchronous functionadapterBuild
that encapsulates the entire process of fetching the latest version of a given framework adapter from npm, logging its version, and then executing the framework-specific build command usingnpx
. - Refactoring of
localbuild.ts
for Genericity: Thelocalbuild.ts
script has been significantly refactored. The previously inline and hardcoded adapter build logic for 'nextjs' has been replaced with a call to the newadapterBuild
helper. The script now accepts a<framework>
argument, making it more dynamic and reusable for different frameworks. - Definition of Supported Frameworks: A new constant array,
SupportedFrameworks
, has been added topackages/@apphosting/common/src/index.ts
. This array currently lists 'nextjs' and 'angular' as supported frameworks and is used inlocalbuild.ts
to validate the framework argument provided by the user.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command>
or @gemini-code-assist <command>
. Below is a summary of the supported commands.
Feature | Command | Description |
---|---|---|
Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/
folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request successfully refactors the adapter build logic into a reusable helper function, improving code structure. However, I've identified a critical issue where an asynchronous function call is not awaited, which would cause the program to terminate prematurely. There's also a high-severity issue with an unhandled error event in a child process. Additionally, I've provided suggestions to improve error messages, enhance type safety, and clean up unused code.
if (SupportedFrameworks.includes(framework)) { | ||
adapterBuild(framework, projectRoot) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two issues here:
- The
adapterBuild
function isasync
but it's not beingawait
ed. This is a critical bug as it will cause the script to exit before the build process completes. - If the provided framework is not in
SupportedFrameworks
, the script exits silently without any feedback to the user. It should print an error message and exit with a non-zero status code.
The suggested code addresses both points.
if (!SupportedFrameworks.includes(framework)) {
console.error(`Framework "${framework}" is not supported. Supported frameworks are: ${SupportedFrameworks.join(", ")}`);
process.exit(1);
}
await adapterBuild(framework, projectRoot);
await new Promise<void>((resolve, reject) => { | ||
const child = spawn("npx", ["-y", "-p", `${adapterName}@${adapterVersion}`, buildCommand], { | ||
cwd: projectRoot, | ||
shell: true, | ||
stdio: "inherit", | ||
}); | ||
|
||
child.on("exit", (code) => { | ||
if (code !== 0) { | ||
reject(new Error(`framework adapter build failed with error code ${code}.`)); | ||
} | ||
resolve(); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spawn
function can emit an 'error' event if it fails to start the process (e.g., if npx
is not found). This event is not currently handled, which could lead to an unhandled promise rejection. You should add an error handler for the child process to ensure all failure modes are caught.
await new Promise<void>((resolve, reject) => {
const child = spawn("npx", ["-y", "-p", `${adapterName}@${adapterVersion}`, buildCommand], {
cwd: projectRoot,
shell: true,
stdio: "inherit",
});
child.on("error", reject);
child.on("exit", (code) => {
if (code !== 0) {
reject(new Error(`framework adapter build failed with error code ${code}.`));
}
resolve();
});
});
@@ -0,0 +1,35 @@ | |||
import { spawn } from "child_process"; | |||
import { program } from "commander"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// we should parse the framework version and use the matching adapter version. | ||
const adapterName = `@apphosting/adapter-${framework}`; | ||
const packumentResponse = await fetch(`https://registry.npmjs.org/${adapterName}`); | ||
if (!packumentResponse.ok) throw new Error(`Something went wrong fetching ${adapterName}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message here is quite generic. It would be more helpful for debugging to include the HTTP status code and text in the error message.
if (!packumentResponse.ok) throw new Error(`Something went wrong fetching ${adapterName}`); | |
if (!packumentResponse.ok) throw new Error(`Failed to fetch ${adapterName}: ${packumentResponse.status} ${packumentResponse.statusText}`); |
import { spawn } from "child_process"; | ||
import { program } from "commander"; | ||
import { yellow, bgRed, bold } from "colorette"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The imports for spawn
, yellow
, bgRed
, and bold
are no longer used in this file after the refactoring. They should be removed to maintain code cleanliness.
import { spawn } from "child_process"; | |
import { program } from "commander"; | |
import { yellow, bgRed, bold } from "colorette"; | |
import { program } from "commander"; |
@@ -2,6 +2,9 @@ | |||
import * as fs from "node:fs"; | |||
import * as path from "node:path"; | |||
|
|||
// List of apphosting supported frameworks. | |||
export const SupportedFrameworks = ['nextjs', 'angular']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For better type safety, you can use as const
to treat SupportedFrameworks
as a readonly tuple of string literals. This allows TypeScript to perform more specific type checking when this array is used.
export const SupportedFrameworks = ['nextjs', 'angular']; | |
export const SupportedFrameworks = ['nextjs', 'angular'] as const; |
- Add interfaces for the apphosting config, while sharing what can be shared with the bundle config - remove unused and duplicate interfaces in adapter-angular - Add 'Build' enum value for envvars availability. This was previously limited to "Runtime" because it was used only for bundle.yaml's envvars which are envvars set by the adapter after a build to be used for runtime. Now the envvars interface will be shared with the apphosting config
@@ -9,27 +9,6 @@ export interface OutputBundleOptions { | |||
needsServerGenerated: boolean; | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
github is the worst tool I have ever encountered.
No description provided.