Skip to content

feat(caretaker): egress cloud run service#28167

Open
chadd28 wants to merge 2 commits into
google-gemini:mainfrom
chadd28:feat/triage-egress
Open

feat(caretaker): egress cloud run service#28167
chadd28 wants to merge 2 commits into
google-gemini:mainfrom
chadd28:feat/triage-egress

Conversation

@chadd28

@chadd28 chadd28 commented Jun 27, 2026

Copy link
Copy Markdown

Summary

Implements the automated caretaker Egress Cloud Run Service into tools/caretaker-agent/cloudrun/egress-service/. This service receives verified action event messages pushed via Cloud Pub/Sub (egress-actions topic) from the Triage Worker and executes automated GitHub operations (such as applying effort labels or posting informational comments) using GitHub App Octokit authentication.

Details

  • Express HTTP Service (src/app.ts, src/server.ts): Provides a lightweight Cloud Run HTTP endpoint to handle GCP Pub/Sub push message delivery, decode Base64 payloads, and return structured health status (/ GET) for liveness/readiness probes.
  • GitHub Action Executor (src/actions/github.ts): Authenticates via GitHub App credentials (@octokit/auth-app) to perform COMMENT and LABEL actions on issues using @octokit/rest.
  • Vitest Unit Test Suite (src/app.test.ts, src/actions/github.test.ts): Comprehensive unit and router test suites.

How to Validate

  1. Navigate to the egress service directory:
cd tools/caretaker-agent/cloudrun/egress-service
npm test    

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

@chadd28 chadd28 requested a review from a team as a code owner June 27, 2026 01:09
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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 adds a new automated egress service to the caretaker agent suite. The service acts as a bridge between GCP Pub/Sub and GitHub, allowing the system to react to verified events by performing automated repository operations. It is built as a lightweight Express application optimized for deployment on Google Cloud Run, ensuring secure and reliable execution of GitHub tasks.

Highlights

  • New Egress Service Implementation: Introduced a new Cloud Run service located in tools/caretaker-agent/cloudrun/egress-service/ designed to process GCP Pub/Sub messages.
  • GitHub Integration: Implemented a GitHub Action executor using Octokit to perform automated tasks like adding labels and posting comments on issues.
  • Robust Error Handling and Validation: Added comprehensive type guards and validation logic to ensure incoming Pub/Sub payloads are correctly formatted before processing.
  • Testing Suite: Added a full unit test suite using Vitest, covering both the HTTP router and the GitHub action execution logic.
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 by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

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 pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the 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 counterproductive. 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.

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.

@github-actions github-actions Bot added the size/xl An extra large PR label Jun 27, 2026
@github-actions

Copy link
Copy Markdown

📊 PR Size: size/XL

  • Lines changed: 4818
  • Additions: +4818
  • Deletions: -0
  • Files changed: 11

@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 introduces a new Node.js/TypeScript Express-based egress service designed to run on Cloud Run and handle GitHub actions via Pub/Sub push subscriptions. Feedback highlights a critical security vulnerability regarding missing authentication on the POST endpoint, and suggests centralizing environment variable parsing and improving string validation for comments.

Comment thread tools/caretaker-agent/cloudrun/egress-service/src/app.ts
Comment on lines +11 to +31
function getRequiredEnvVar(name: string): string {
const value = process.env[name];
if (!value) {
throw new Error(`Missing required environment variable: ${name}`);
}
return value;
}

export async function handleEgressEvent(event: EgressEvent): Promise<void> {
const appId = getRequiredEnvVar('GH_APP_ID');
const privateKey = getRequiredEnvVar('GH_PRIVATE_KEY');
const installationId = getRequiredEnvVar('GH_INSTALLATION_ID');

const octokit = new Octokit({
authStrategy: createAppAuth,
auth: {
appId: Number(appId),
privateKey: privateKey.replace(/\\n/g, '\n'),
installationId: Number(installationId),
},
});

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

To adhere to the general rules, environment variable parsing and normalization (such as converting to numbers and replacing escaped newlines) should not be scattered or performed repeatedly inside request handlers. Instead, centralize this logic into a dedicated configuration helper. This also prevents redundant parsing on every request and ensures that any configuration errors are handled cleanly.

function getRequiredEnvVar(name: string): string {
  const value = process.env[name];
  if (!value) {
    throw new Error('Missing required environment variable: ' + name);
  }
  return value;
}

interface GitHubConfig {
  appId: number;
  privateKey: string;
  installationId: number;
}

function getGitHubConfig(): GitHubConfig {
  const appId = Number(getRequiredEnvVar('GH_APP_ID'));
  const privateKey = getRequiredEnvVar('GH_PRIVATE_KEY').replace(/\\n/g, '\n');
  const installationId = Number(getRequiredEnvVar('GH_INSTALLATION_ID'));

  if (isNaN(appId)) {
    throw new Error('GH_APP_ID must be a valid number');
  }
  if (isNaN(installationId)) {
    throw new Error('GH_INSTALLATION_ID must be a valid number');
  }

  return { appId, privateKey, installationId };
}

export async function handleEgressEvent(event: EgressEvent): Promise<void> {
  const config = getGitHubConfig();

  const octokit = new Octokit({
    authStrategy: createAppAuth,
    auth: {
      appId: config.appId,
      privateKey: config.privateKey,
      installationId: config.installationId,
    },
  });
References
  1. Do not scatter environment variable normalization (such as trimming or case conversion) across multiple files. If environment variables need to be parsed or sanitized, perform this consistently in a single centralized location.

Comment on lines +37 to +40
case 'COMMENT':
if (!payload.commentBody) {
throw new Error('Missing commentBody for COMMENT action');
}

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

To prevent whitespace-only values from being accepted, trim the string first and then check for emptiness before executing the action. This aligns with the general rules for validating string parameters from tools.

Suggested change
case 'COMMENT':
if (!payload.commentBody) {
throw new Error('Missing commentBody for COMMENT action');
}
case 'COMMENT':
if (!payload.commentBody || payload.commentBody.trim() === '') {
throw new Error('Missing commentBody for COMMENT action');
}
References
  1. When validating string parameters from tools, trim the string first and then check for emptiness to prevent whitespace-only values from being accepted.

@gemini-cli gemini-cli Bot added the status/need-issue Pull requests that need to have an associated issue. label Jun 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl An extra large PR status/need-issue Pull requests that need to have an associated issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant