Skip to content

Fixed conversion of environment variables to number types with GitHub Copilot 2#155

Open
ryo8000 wants to merge 1 commit into
mainfrom
copilot/env
Open

Fixed conversion of environment variables to number types with GitHub Copilot 2#155
ryo8000 wants to merge 1 commit into
mainfrom
copilot/env

Conversation

@ryo8000

@ryo8000 ryo8000 commented Aug 18, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features
    • Stricter validation for environment configuration (timeouts and port) with clear error messages and safe integer checks.
    • Fail-fast startup on invalid or out-of-range values; sensible defaults remain when unset.
  • Bug Fixes
    • Prevents silent fallbacks and inconsistent settings by enforcing logical timeout ordering (keep-alive < headers < request).
  • Tests
    • Added unit tests covering invalid values, ordering rules, and safe-range enforcement for environment variables.

@coderabbitai

coderabbitai Bot commented Aug 18, 2025

Copy link
Copy Markdown

Walkthrough

Environment variable handling is refactored to parse and validate numeric values with explicit errors, introduce ordering checks among timeouts, and compute maxDelay and port via validated helpers. Tests are added to assert rejection on invalid integer inputs and out-of-range values for all relevant variables, including PORT beyond safe integer limits.

Changes

Cohort / File(s) Summary of edits
Env parsing and validation
src/env.ts
Added safe-integer parsing wrappers for timeouts, maxDelay, and port with explicit errors; enforced ordering constraints (keepAliveTimeout < headersTimeout < requestTimeout); replaced inline env reads with computed variables; preserved existing flags.
Unit tests for invalid env values
tests/ut/env.test.ts
Added tests ensuring loadEnv rejects invalid/non-integer and out-of-range values for HEADERS_TIMEOUT, REQUEST_TIMEOUT, KEEP_ALIVE_TIMEOUT, MAX_DELAY, and PORT, including values beyond Number.MAX_SAFE_INTEGER.

Sequence Diagram(s)

sequenceDiagram
  participant Proc as process.env
  participant Env as loadEnv (src/env.ts)
  participant Parser as toSafeInteger wrappers
  participant Validator as Ordering checks
  participant Export as environment export

  Proc->>Env: Load variables
  Env->>Parser: Parse HEADERS_TIMEOUT / REQUEST_TIMEOUT / KEEP_ALIVE_TIMEOUT / MAX_DELAY / PORT
  Parser-->>Env: Numbers or throw on invalid
  Env->>Validator: Verify keepAlive < headers < request
  Validator-->>Env: OK or throw
  Env->>Export: Build environment object
  Export-->>Caller: Return config
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A rabbit twitches whiskers, oh hooray!
We parse the ports and timeouts, clear as day.
No wobbly numbers hop past the gate,
Bad carrots tossed—too big, too late.
With ordered ticks and bounds in view,
Our burrow boots clean configs anew. 🥕✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch copilot/env

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @ryo8000, 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 enhances the robustness of environment variable parsing by replacing simple Number() conversions with a more secure and error-handling method. The changes ensure that numerical environment variables are strictly validated, throwing explicit errors for invalid inputs. This prevents potential runtime issues caused by malformed configuration values and improves the overall stability of the application's startup process.

Highlights

  • Robust Environment Variable Parsing: Replaced direct Number() conversions for HEADERS_TIMEOUT, REQUEST_TIMEOUT, KEEP_ALIVE_TIMEOUT, MAX_DELAY, and PORT with a custom toSafeInteger utility. This new approach includes explicit checks for undefined values and throws detailed errors for non-integer or out-of-range inputs.
  • Enhanced Error Handling: Introduced specific and descriptive error messages for each environment variable when an invalid numerical value is provided, making it significantly easier to diagnose configuration issues.
  • Comprehensive Unit Tests: Added comprehensive unit tests to env.test.ts covering various invalid scenarios for environment variables, including non-numeric strings, floats, scientific notation, and values exceeding Number.MAX_SAFE_INTEGER, ensuring the new error handling mechanism functions correctly.
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.


String to number, oh! Careful parsing, errors caught, Code runs safe and sound.

Footnotes

  1. 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.

@ryo8000 ryo8000 changed the title Fixed conversion of environment variables to number types Fixed conversion of environment variables to number types with GitHub Copilot 2 Aug 18, 2025

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 improves the robustness of environment variable parsing by validating that numeric values are indeed valid integers and throwing an error if they are not. This is a good improvement over the previous behavior of silently using default values. The added tests effectively cover these new error cases.

My main feedback is on the implementation in src/env.ts, where there is significant code duplication for parsing each numeric environment variable. I've suggested refactoring this into a helper function to improve maintainability and readability.

Comment thread src/env.ts
Comment on lines +3 to +69
const headersTimeoutValue = process.env['HEADERS_TIMEOUT'];
const requestTimeoutValue = process.env['REQUEST_TIMEOUT'];
const keepAliveTimeoutValue = process.env['KEEP_ALIVE_TIMEOUT'];
const maxDelayValue = process.env['MAX_DELAY'];
const portValue = process.env['PORT'];

// Convert environment variables with error handling
const headersTimeout =
headersTimeoutValue !== undefined
? (() => {
const parsed = toSafeInteger(headersTimeoutValue);
if (parsed === undefined) {
throw new Error(
`Invalid HEADERS_TIMEOUT value: "${headersTimeoutValue}". Must be a valid integer.`
);
}
return parsed;
})()
: 10000;

const requestTimeout =
requestTimeoutValue !== undefined
? (() => {
const parsed = toSafeInteger(requestTimeoutValue);
if (parsed === undefined) {
throw new Error(
`Invalid REQUEST_TIMEOUT value: "${requestTimeoutValue}". Must be a valid integer.`
);
}
return parsed;
})()
: 30000;

const keepAliveTimeout =
keepAliveTimeoutValue !== undefined
? (() => {
const parsed = toSafeInteger(keepAliveTimeoutValue);
if (parsed === undefined) {
throw new Error(
`Invalid KEEP_ALIVE_TIMEOUT value: "${keepAliveTimeoutValue}". Must be a valid integer.`
);
}
return parsed;
})()
: 5000;

const maxDelay =
maxDelayValue !== undefined
? (() => {
const parsed = toSafeInteger(maxDelayValue);
if (parsed === undefined) {
throw new Error(`Invalid MAX_DELAY value: "${maxDelayValue}". Must be a valid integer.`);
}
return parsed;
})()
: 10000;

const port =
portValue !== undefined
? (() => {
const parsed = toSafeInteger(portValue);
if (parsed === undefined) {
throw new Error(`Invalid PORT value: "${portValue}". Must be a valid integer.`);
}
return parsed;
})()
: 8000;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The logic for parsing and validating numeric environment variables is repeated five times. This code duplication makes the code harder to read and maintain. Any future changes to this logic would need to be applied in all five places, which is error-prone.

To improve this, you can extract the parsing logic into a reusable helper function. This will make the code more concise, readable, and easier to maintain, following the DRY (Don't Repeat Yourself) principle.

Suggested change
const headersTimeoutValue = process.env['HEADERS_TIMEOUT'];
const requestTimeoutValue = process.env['REQUEST_TIMEOUT'];
const keepAliveTimeoutValue = process.env['KEEP_ALIVE_TIMEOUT'];
const maxDelayValue = process.env['MAX_DELAY'];
const portValue = process.env['PORT'];
// Convert environment variables with error handling
const headersTimeout =
headersTimeoutValue !== undefined
? (() => {
const parsed = toSafeInteger(headersTimeoutValue);
if (parsed === undefined) {
throw new Error(
`Invalid HEADERS_TIMEOUT value: "${headersTimeoutValue}". Must be a valid integer.`
);
}
return parsed;
})()
: 10000;
const requestTimeout =
requestTimeoutValue !== undefined
? (() => {
const parsed = toSafeInteger(requestTimeoutValue);
if (parsed === undefined) {
throw new Error(
`Invalid REQUEST_TIMEOUT value: "${requestTimeoutValue}". Must be a valid integer.`
);
}
return parsed;
})()
: 30000;
const keepAliveTimeout =
keepAliveTimeoutValue !== undefined
? (() => {
const parsed = toSafeInteger(keepAliveTimeoutValue);
if (parsed === undefined) {
throw new Error(
`Invalid KEEP_ALIVE_TIMEOUT value: "${keepAliveTimeoutValue}". Must be a valid integer.`
);
}
return parsed;
})()
: 5000;
const maxDelay =
maxDelayValue !== undefined
? (() => {
const parsed = toSafeInteger(maxDelayValue);
if (parsed === undefined) {
throw new Error(`Invalid MAX_DELAY value: "${maxDelayValue}". Must be a valid integer.`);
}
return parsed;
})()
: 10000;
const port =
portValue !== undefined
? (() => {
const parsed = toSafeInteger(portValue);
if (parsed === undefined) {
throw new Error(`Invalid PORT value: "${portValue}". Must be a valid integer.`);
}
return parsed;
})()
: 8000;
function getNumericEnv(name: string, defaultValue: number): number {
const value = process.env[name];
if (value === undefined) {
return defaultValue;
}
const parsed = toSafeInteger(value);
if (parsed === undefined) {
throw new Error(`Invalid ${name} value: "${value}". Must be a valid integer.`);
}
return parsed;
}
// Convert environment variables with error handling
const headersTimeout = getNumericEnv('HEADERS_TIMEOUT', 10000);
const requestTimeout = getNumericEnv('REQUEST_TIMEOUT', 30000);
const keepAliveTimeout = getNumericEnv('KEEP_ALIVE_TIMEOUT', 5000);
const maxDelay = getNumericEnv('MAX_DELAY', 10000);
const port = getNumericEnv('PORT', 8000);

@ryo8000 ryo8000 added enhancement New feature or request experiment Experiment labels Aug 18, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
tests/ut/env.test.ts (2)

84-90: Prevent test flakiness by clearing numeric env vars in this block

If CI (or a dev shell) happens to define any of these env vars, these tests could behave unexpectedly. Clearing them at the start of this describe keeps the tests hermetic without relying on global beforeEach.

Apply this diff to insert a local beforeEach:

 describe('Invalid environment variable values', () => {
+  beforeEach(() => {
+    delete process.env.HEADERS_TIMEOUT;
+    delete process.env.REQUEST_TIMEOUT;
+    delete process.env.KEEP_ALIVE_TIMEOUT;
+    delete process.env.MAX_DELAY;
+    delete process.env.PORT;
+  });

84-132: Reduce duplication via table-driven tests (optional)

You can collapse the repetitive invalid-input tests into a single parameterized test for readability and maintainability.

Example:

it.each([
  ['HEADERS_TIMEOUT', 'invalid'],
  ['REQUEST_TIMEOUT', '12.5'],
  ['KEEP_ALIVE_TIMEOUT', 'abc123'],
  ['MAX_DELAY', '1e5'],
  ['PORT', 'port8000'],
] as const)('should throw an error for invalid %s value', async (name, value) => {
  process.env[name] = value;
  await expect(loadEnv()).rejects.toThrow(
    `Invalid ${name} value: "${value}". Must be a valid integer.`
  );
});
src/env.ts (2)

71-81: Add basic range validation for timeouts, maxDelay, and port

Currently, negative values for timeouts/maxDelay or out-of-range ports (e.g., 65536 or -1) would pass parsing but are invalid at runtime. Add sanity checks before the ordering assertions.

Apply this diff to insert the checks just before the ordering validations:

- 
+// Sanity range checks
+if (headersTimeout < 0 || keepAliveTimeout < 0 || requestTimeout < 0) {
+  throw new Error(
+    'Invalid timeout configuration: values must be non-negative integers (ms).'
+  );
+}
+if (maxDelay < 0) {
+  throw new Error(
+    `Invalid MAX_DELAY value: "${maxDelayValue}". Must be a non-negative integer.`
+  );
+}
+if (port < 0 || port > 65535) {
+  throw new Error(
+    `Invalid PORT value: "${portValue}". Must be an integer between 0 and 65535.`
+  );
+}
+
 if (headersTimeout <= keepAliveTimeout) {
   throw new Error(
     `Invalid timeout configuration: headersTimeout (${headersTimeout}ms) must be greater than keepAliveTimeout (${keepAliveTimeout}ms)`
   );
 }

If you adopt these checks, consider adding a few targeted tests (e.g., PORT='-1', PORT='65536', MAX_DELAY='-1') to lock behavior.


9-69: Reduce repetition with a small helper to read safe integers

The IIFE pattern repeats the same parse/throw/default logic five times. A tiny helper improves readability and makes future additions cheaper.

Sketch:

const readSafeInt = (name: 'HEADERS_TIMEOUT' | 'REQUEST_TIMEOUT' | 'KEEP_ALIVE_TIMEOUT' | 'MAX_DELAY' | 'PORT', defaultValue: number): number => {
  const raw = process.env[name];
  if (raw === undefined) return defaultValue;
  const parsed = toSafeInteger(raw);
  if (parsed === undefined) {
    throw new Error(`Invalid ${name} value: "${raw}". Must be a valid integer.`);
  }
  return parsed;
};

// Usage:
const headersTimeout = readSafeInt('HEADERS_TIMEOUT', 10000);
const requestTimeout = readSafeInt('REQUEST_TIMEOUT', 30000);
const keepAliveTimeout = readSafeInt('KEEP_ALIVE_TIMEOUT', 5000);
const maxDelay = readSafeInt('MAX_DELAY', 10000);
const port = readSafeInt('PORT', 8000);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a640e66 and e37bca8.

📒 Files selected for processing (2)
  • src/env.ts (2 hunks)
  • tests/ut/env.test.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
tests/ut/env.test.ts (1)
tests/ut/utils/number.test.ts (2)
  • validIntegerTestCases (4-19)
  • describe (3-39)
src/env.ts (1)
src/utils/number.ts (1)
  • toSafeInteger (16-28)
🔇 Additional comments (3)
tests/ut/env.test.ts (1)

84-132: Solid negative-path coverage with precise error assertions

The new "Invalid environment variable values" suite cleanly exercises parsing failures for all numeric env vars and validates exact error messages. Nice job covering the out-of-safe-range case too.

src/env.ts (2)

1-70: Explicit, safe integer parsing with early failures is a clear upgrade

Parsing via toSafeInteger with explicit errors and sensible defaults improves correctness and eliminates silent coercions. The structure reads well and aligns with the new tests.


83-93: Environment export looks consistent with computed values

Using the validated, computed values in the exported object keeps consumers simple and reliable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request experiment Experiment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant