Skip to content

RG-T132 Buidl fix - #126

Merged
ucswift merged 1 commit into
masterfrom
develop
Aug 20, 2026
Merged

RG-T132 Buidl fix#126
ucswift merged 1 commit into
masterfrom
develop

Conversation

@ucswift

@ucswift ucswift commented Aug 20, 2026

Copy link
Copy Markdown
Member

Summary

This PR fixes the app icon badge build flow by replacing the direct app-icon-badge Expo plugin usage with a local plugin that generates badged icons before Expo prebuild consumes them.

What changed

  • Switched app.config.ts to use a local appIconBadge.plugin.js instead of the package-provided app-icon-badge plugin.
  • Added a custom app icon badge plugin that:
    • updates the app, iOS, and Android adaptive foreground icon paths to generated badged icon files under .expo/app-icon-badge
    • generates those files synchronously during config resolution
    • caches generation based on source icon file metadata to avoid unnecessary regeneration
  • Added a scripts/generate-icon-badges.js helper script to create the badged icon assets and validate that the output files were written correctly.
  • Added a patch for app-icon-badge so badge image writes are properly awaited before returning.

Functional impact

This change prevents build/prebuild failures on clean environments such as EAS where Expo may try to read generated badged icon files before they exist or before they are fully written. It ensures the required icon assets are ready and non-empty before Expo continues processing them.

@Resgrid-Bot

Resgrid-Bot commented Aug 20, 2026

Copy link
Copy Markdown

Code Review Completed! 🔥

The code review was successfully completed based on your current configurations.

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Validate Business Logic: Ask Kody to validate your code against business rules by adding a comment with the @kody -v business-logic command.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug
Performance
Security
Business Logic

Access your configuration settings here.

@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your current included review allowance is based on your included PR review attempts over the past 7 days.

Next review available in: 22 minutes

Limit details: You’ve used the included review currently available. Your 62 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 28272c17-881b-4e30-96e9-231bfe935926

📥 Commits

Reviewing files that changed from the base of the PR and between 13c48e7 and 7380bb0.

📒 Files selected for processing (4)
  • app.config.ts
  • appIconBadge.plugin.js
  • patches/app-icon-badge+0.1.2.patch
  • scripts/generate-icon-badges.js

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

Comment thread appIconBadge.plugin.js
Comment on lines +40 to +42
return [DST_ICON, DST_IOS_ICON, DST_ADAPTIVE_ICON].every((dst) => {
const file = path.join(projectRoot, dst);
return !fs.existsSync(file) || fs.statSync(file).size > 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-review Bug high

Stale file predicate in isUpToDate in appIconBadge.plugin.js marks missing generated icons as valid because !fs.existsSync(file) returns true. Require every destination for the current jobs to exist and have fs.statSync(file).size > 0 before returning true, or .expo/app-icon-badge/*.png deletion after a successful run can leave config.icon, ios.icon, and adaptiveIcon.foregroundImage pointing to non-existent files and break the next Expo icon mods prebuild.

return jobs.every(({ dstPath }) => {
  const file = path.join(projectRoot, dstPath);
  return fs.existsSync(file) && fs.statSync(file).size > 0;
});
Prompt for LLM

File appIconBadge.plugin.js:

Line 40 to 42:

Stale file predicate in `isUpToDate` in `appIconBadge.plugin.js` marks missing generated icons as valid because `!fs.existsSync(file)` returns true. Require every destination for the current `jobs` to exist and have `fs.statSync(file).size > 0` before returning true, or `.expo/app-icon-badge/*.png` deletion after a successful run can leave `config.icon`, `ios.icon`, and `adaptiveIcon.foregroundImage` pointing to non-existent files and break the next Expo icon mods prebuild.

Suggested Code:

  return jobs.every(({ dstPath }) => {
    const file = path.join(projectRoot, dstPath);
    return fs.existsSync(file) && fs.statSync(file).size > 0;
  });

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

Comment thread appIconBadge.plugin.js
});
};

const withAppIconBadge = (config, options = {}) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-review Kody Rules high

Invalid rule match in appIconBadge.plugin.js: the reported .bind() or inline arrow function usage in JSX props does not apply to const withAppIconBadge = (config, options = {}) => { because this file context does not show JSX props. Remove this suggestion unless a specific JSX prop location is identified.

Kody rule violation: Avoid using .bind() or arrow functions in JSX props

Prompt for LLM

File appIconBadge.plugin.js:

Line 46:

Invalid rule match in `appIconBadge.plugin.js`: the reported `.bind()` or inline arrow function usage in JSX props does not apply to `const withAppIconBadge = (config, options = {}) => {` because this file context does not show JSX props. Remove this suggestion unless a specific JSX prop location is identified.

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

Comment thread appIconBadge.plugin.js
dstPath: path.join(projectRoot, job.dstPath),
}));

execFileSync(process.execPath, [path.join(projectRoot, 'scripts', 'generate-icon-badges.js'), JSON.stringify(absoluteJobs)], {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-review Kody Rules high

Unhandled external process failure in appIconBadge.plugin.js leaves execFileSync(process.execPath, [path.join(projectRoot, 'scripts', 'generate-icon-badges.js'), JSON.stringify(absoluteJobs)], { ... }) without contextual diagnostics when scripts are missing, paths are invalid, or the child exits non-zero. Wrap the call in try/catch and rethrow with projectRoot context, as also required at patches/app-icon-badge+0.1.2.patch:10-10, patches/app-icon-badge+0.1.2.patch:23-23, patches/app-icon-badge+0.1.2.patch:36-36, and scripts/generate-icon-badges.js:17-17.

Kody rule violation: Add try-catch blocks for external calls

try {
  execFileSync(process.execPath, [path.join(projectRoot, 'scripts', 'generate-icon-badges.js'), JSON.stringify(absoluteJobs)], {
    cwd: projectRoot,
    stdio: 'inherit',
  });
} catch (err) {
  throw new Error(`generate-icon-badges failed for projectRoot=${projectRoot}: ${err instanceof Error ? err.message : String(err)}`);
}
Prompt for LLM

File appIconBadge.plugin.js:

Line 91:

Unhandled external process failure in `appIconBadge.plugin.js` leaves `execFileSync(process.execPath, [path.join(projectRoot, 'scripts', 'generate-icon-badges.js'), JSON.stringify(absoluteJobs)], { ... })` without contextual diagnostics when scripts are missing, paths are invalid, or the child exits non-zero. Wrap the call in `try/catch` and rethrow with `projectRoot` context, as also required at `patches/app-icon-badge+0.1.2.patch:10-10`, `patches/app-icon-badge+0.1.2.patch:23-23`, `patches/app-icon-badge+0.1.2.patch:36-36`, and `scripts/generate-icon-badges.js:17-17`.

Suggested Code:

  try {
    execFileSync(process.execPath, [path.join(projectRoot, 'scripts', 'generate-icon-badges.js'), JSON.stringify(absoluteJobs)], {
      cwd: projectRoot,
      stdio: 'inherit',
    });
  } catch (err) {
    throw new Error(`generate-icon-badges failed for projectRoot=${projectRoot}: ${err instanceof Error ? err.message : String(err)}`);
  }

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

Comment thread appIconBadge.plugin.js
dstPath: path.join(projectRoot, job.dstPath),
}));

execFileSync(process.execPath, [path.join(projectRoot, 'scripts', 'generate-icon-badges.js'), JSON.stringify(absoluteJobs)], {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-review Kody Rules high

Mutable path risk in appIconBadge.plugin.js: path.join(projectRoot, 'scripts', 'generate-icon-badges.js') derives an executable target from projectRoot without validation. Constrain scriptPath to the expected allowlisted path.join(projectRoot, 'scripts') location before passing it to execFileSync, even though the call uses argv rather than a shell string.

Kody rule violation: Avoid building system commands from user input

const scriptPath = path.join(projectRoot, 'scripts', 'generate-icon-badges.js');
if (!scriptPath.startsWith(path.join(projectRoot, 'scripts'))) {
  throw new Error('Invalid script path');
}
execFileSync(process.execPath, [scriptPath, JSON.stringify(absoluteJobs)], {
  cwd: projectRoot,
  stdio: 'inherit',
});
Prompt for LLM

File appIconBadge.plugin.js:

Line 91:

Mutable path risk in `appIconBadge.plugin.js`: `path.join(projectRoot, 'scripts', 'generate-icon-badges.js')` derives an executable target from `projectRoot` without validation. Constrain `scriptPath` to the expected allowlisted `path.join(projectRoot, 'scripts')` location before passing it to `execFileSync`, even though the call uses argv rather than a shell string.

Suggested Code:

  const scriptPath = path.join(projectRoot, 'scripts', 'generate-icon-badges.js');
  if (!scriptPath.startsWith(path.join(projectRoot, 'scripts'))) {
    throw new Error('Invalid script path');
  }
  execFileSync(process.execPath, [scriptPath, JSON.stringify(absoluteJobs)], {
    cwd: projectRoot,
    stdio: 'inherit',
  });

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

icon
});
- resultImage.writeAsync(resultFilename);
+ yield resultImage.writeAsync(resultFilename);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-review Kody Rules high

Unhandled promise rejection in patches/app-icon-badge+0.1.2.patch leaves yield resultImage.writeAsync(resultFilename); without local failure diagnostics. Guard writeAsync with try/catch, log structured context including op: 'addBadge.writeAsync' and resultFilename, and rethrow, including at patches/app-icon-badge+0.1.2.patch:23-23 and patches/app-icon-badge+0.1.2.patch:36-36.

Kody rule violation: Handle async operations with proper error handling

try {
  yield resultImage.writeAsync(resultFilename);
} catch (err) {
  logger.error('writeAsync failed', { op: 'addBadge.writeAsync', resultFilename, err });
  throw err;
}
Prompt for LLM

File patches/app-icon-badge+0.1.2.patch:

Line 10:

Unhandled promise rejection in `patches/app-icon-badge+0.1.2.patch` leaves `yield resultImage.writeAsync(resultFilename);` without local failure diagnostics. Guard `writeAsync` with `try/catch`, log structured context including `op: 'addBadge.writeAsync'` and `resultFilename`, and rethrow, including at `patches/app-icon-badge+0.1.2.patch:23-23` and `patches/app-icon-badge+0.1.2.patch:36-36`.

Suggested Code:

try {
  yield resultImage.writeAsync(resultFilename);
} catch (err) {
  logger.error('writeAsync failed', { op: 'addBadge.writeAsync', resultFilename, err });
  throw err;
}

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

};

main().catch((error) => {
console.error(error);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-review Kody Rules high

Insufficient error context in scripts/generate-icon-badges.js because console.error(error); logs only the raw error object. Log structured metadata including the operation name and process.argv?.[2] so generate-icon-badges failures can be traced and diagnosed.

Kody rule violation: Include error context in structured logs

console.error('generate-icon-badges failed', {
  op: 'generate-icon-badges',
  inputPath: process.argv?.[2],
  error,
});
Prompt for LLM

File scripts/generate-icon-badges.js:

Line 27:

Insufficient error context in `scripts/generate-icon-badges.js` because `console.error(error);` logs only the raw error object. Log structured metadata including the operation name and `process.argv?.[2]` so `generate-icon-badges` failures can be traced and diagnosed.

Suggested Code:

console.error('generate-icon-badges failed', {
  op: 'generate-icon-badges',
  inputPath: process.argv?.[2],
  error,
});

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

@ucswift

ucswift commented Aug 20, 2026

Copy link
Copy Markdown
Member Author

Approve

@github-actions github-actions 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.

This PR is approved.

@ucswift
ucswift merged commit ddd494b into master Aug 20, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants