Skip to content

Conversation

@middt
Copy link
Contributor

@middt middt commented Dec 5, 2025

Summary by Sourcery

Improve installation robustness in CI and adjust non-interactive setup behavior.

Bug Fixes:

  • Prevent CI workflow failures by retrying npm dependency installation with exponential backoff.
  • Avoid interactive setup prompts and failures in CI by broadening non-interactive detection and skipping setup logic accordingly.
  • Ensure postinstall does not fail the install when setup.js exits with an error in non-interactive environments.

Enhancements:

  • Add a reusable shell helper in the build workflow for dependency installation with retries and clearer logging.

Summary by CodeRabbit

  • Chores
    • Enhanced build installation reliability with automatic retry logic and exponential backoff to handle transient failures during dependency installation.
    • Improved continuous integration and automated deployment setup with better environment detection and graceful error recovery mechanisms for smoother builds.

✏️ Tip: You can customize this high-level summary in your review settings.

@sourcery-ai
Copy link

sourcery-ai bot commented Dec 5, 2025

Reviewer's Guide

Adds retry logic to npm installs in the CI workflow, makes the setup script fully non-interactive/CI-safe, and ensures postinstall never fails the install if setup.js exits with an error.

Sequence diagram for CI npm install with retry workflow

sequenceDiagram
    participant GitHubActionsRunner as GitHubActionsRunner
    participant InstallStep as InstallDependenciesStep
    participant Shell as Shell
    participant NPM as npm

    GitHubActionsRunner->>InstallStep: start
    InstallStep->>Shell: run install_with_retry

    loop up to 3 attempts
        Shell->>Shell: check for package-lock.json
        alt package-lock.json exists
            Shell->>NPM: npm ci
        else no package-lock.json
            Shell->>NPM: npm install
        end
        alt install succeeds
            NPM-->>Shell: success
            Shell-->>InstallStep: exit 0
            InstallStep-->>GitHubActionsRunner: success
            Shell->>Shell: break loop on success
        else install fails and attempts remaining
            NPM-->>Shell: failure
            Shell->>Shell: sleep with exponential backoff
        else install fails and no attempts remaining
            NPM-->>Shell: failure
            Shell-->>InstallStep: exit 1
            InstallStep-->>GitHubActionsRunner: failure
        end
    end
Loading

Sequence diagram for postinstall behavior with setup.js in CI

sequenceDiagram
    participant NPM as npm
    participant Postinstall as postinstallScript
    participant Setup as setup_js
    participant SyncSchema as sync_schema_script

    NPM->>Postinstall: run (node setup.js || true) && npm run sync-schema
    Postinstall->>Setup: node setup.js
    alt setup runs in CI/non-interactive
        Setup-->>Postinstall: exit 0 or non-zero (ignored)
    else setup runs interactively
        Setup-->>Postinstall: exit 0 or non-zero (ignored)
    end
    Postinstall->>Postinstall: logical OR converts failure to success
    Postinstall->>SyncSchema: npm run sync-schema
    SyncSchema-->>Postinstall: success or failure (propagated)
    Postinstall-->>NPM: overall postinstall status depends only on sync-schema
Loading

Flow diagram for non-interactive setup.js behavior in CI

flowchart TD
    A["start setup"] --> B["isInstalledAsDependency?"]
    B -->|yes| C["return (skip setup)"]
    B -->|no| D["domainFromConfig = getDomainFromConfig"]

    D --> E["isDomainFolderConfigured?"]
    E -->|yes| F["isNonInteractive?
(!stdin TTY or CI/GITHUB_ACTIONS/NPM_CONFIG_INTERACTIVE flags)"]
    F -->|yes| G["return (skip silently)"]
    F -->|no| H["print vNext header and domain already configured messages"]
    H --> I["return"]

    E -->|no| J["isNonInteractive?"]
    J -->|yes| K["does touch file exist?"]
    K -->|no| L["return (skip silently)"]
    K -->|yes| M["return (skip silently, no prompts)"]

    J -->|no| N["print vNext header"]
    N --> O["isAlreadySetup?"]
    O -->|yes| P["print already set up message and return"]
    O -->|no| Q["continue interactive setup prompts"]
Loading

File-Level Changes

Change Details Files
Harden npm dependency installation in CI with a retryable shell function.
  • Replace simple conditional npm ci/npm install block with an install_with_retry shell function.
  • Implement up to three attempts with exponential backoff and status messaging.
  • Maintain logic to prefer npm ci when package-lock.json exists, falling back to npm install otherwise.
.github/workflows/build-and-publish.yml
Make setup.js aware of CI environments and fully non-interactive during automation.
  • Extend non-interactive detection to include GITHUB_ACTIONS and CI=1 environment variables.
  • Skip all setup output and prompts when a domain is already configured and environment is non-interactive.
  • Short-circuit setup early in any non-interactive/CI environment, returning without prompts or logs even if touch is missing or present.
setup.js
Prevent postinstall failures from breaking npm install in CI and local automation.
  • Wrap node setup.js in postinstall with `

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@middt middt merged commit 1edbc1a into release-v0.0 Dec 5, 2025
1 of 4 checks passed
@gemini-code-assist
Copy link

Summary of Changes

Hello @middt, 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 focuses on enhancing the project's setup and post-installation processes to be more robust and compatible with Continuous Integration (CI) environments. It modifies the package.json to ensure critical scripts run reliably and refines the setup.js script to intelligently detect and adapt its behavior in non-interactive settings, thereby preventing manual intervention or failures during automated builds and deployments.

Highlights

  • Robust CI/CD Workflow: The postinstall script in package.json has been updated to ensure that the sync-schema command will always execute, even if the setup.js script encounters an error. This is achieved by using (node setup.js || true), making the setup process more resilient in automated environments.
  • Enhanced Non-Interactive Environment Detection: The isNonInteractive function in setup.js has been improved to more comprehensively detect various Continuous Integration (CI) environments. It now checks for GITHUB_ACTIONS === 'true' and CI === '1' in addition to existing checks, ensuring better compatibility with different CI platforms.
  • Silent Setup in CI: The setup.js script now includes conditional logic to operate silently and avoid interactive prompts when running in non-interactive (CI) environments. This prevents the script from blocking or failing in CI if a domain is already configured or if certain expected files (like 'touch') are not present, streamlining automated deployments.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/build-and-publish.yml
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 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

  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.

@coderabbitai
Copy link

coderabbitai bot commented Dec 5, 2025

Caution

Review failed

The pull request is closed.

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'review'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • 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

Walkthrough

The changes enhance build and setup resilience by adding retry logic to npm dependency installation with exponential backoff, making the postinstall script continue gracefully on setup failures, and improving setup.js to detect CI environments and skip interactive prompts in non-interactive mode while maintaining compatibility with domain-configured paths.

Changes

Cohort / File(s) Change Summary
Build Workflow Retry Logic
.github/workflows/build-and-publish.yml
Introduces install_with_retry function that attempts npm install/ci up to 3 times with exponential backoff (5s initial, doubling per retry), using npm ci when package-lock.json exists, otherwise npm install; includes per-attempt progress reporting.
Setup and Installation Robustness
package.json, setup.js
Modified postinstall script to continue execution via (node setup.js || true) fallback; enhanced setup.js with CI environment detection (CI, GITHUB_ACTIONS flags) to suppress interactive prompts and domain-configured path handling in non-interactive scenarios; adds early guard for missing touch directory and moves setup banner display to interactive mode only.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Specific areas requiring attention:
    • Bash retry logic in workflow file: verify exponential backoff calculation and retry termination conditions are correct
    • CI environment variable detection in setup.js: ensure all relevant CI platform flags are covered
    • Fallback behavior in postinstall script: confirm that continuing on setup.js failure doesn't mask legitimate setup errors

Possibly related PRs

  • minor fix #1 – Modifies similar setup.js non-interactive and domain-configuration handling logic, including isNonInteractive checks and getDomainName retrieval paths.

Poem

🐰 Retry with grace, through CI we race,
Exponential backoff at a gentle pace,
Setup runs quiet in pipelines bright,
No prompts to trouble the build's pure flight,
Domain-aware and resilient strong,

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch master

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7050004 and eb5c999.

📒 Files selected for processing (3)
  • .github/workflows/build-and-publish.yml (1 hunks)
  • package.json (1 hunks)
  • setup.js (2 hunks)

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

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

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • In setup.js, the isNonInteractive() block that checks for fs.existsSync('touch') always returns regardless of the check, making the touch file condition ineffective; either remove the redundant check or adjust the logic so the presence/absence of touch actually changes behavior.
  • The change to postinstall ((node setup.js || true) && npm run sync-schema) will mask any real errors from setup.js in local development as well as CI; consider scoping the || true to CI-only via an environment check so developers still see failures when setup breaks.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `setup.js`, the `isNonInteractive()` block that checks for `fs.existsSync('touch')` always returns regardless of the check, making the `touch` file condition ineffective; either remove the redundant check or adjust the logic so the presence/absence of `touch` actually changes behavior.
- The change to `postinstall` (`(node setup.js || true) && npm run sync-schema`) will mask any real errors from `setup.js` in local development as well as CI; consider scoping the `|| true` to CI-only via an environment check so developers still see failures when setup breaks.

## Individual Comments

### Comment 1
<location> `setup.js:243-252` </location>
<code_context>
   const domainFromConfig = getDomainFromConfig();
   if (domainFromConfig && isDomainFolderConfigured()) {
+    // In CI/non-interactive mode, skip silently
+    if (isNonInteractive()) {
+      return;
+    }
+    // In interactive mode, show message
+    console.log('🚀 vNext Template Setup');
+    console.log('=======================\n');
     console.log(`✅ Domain "${domainFromConfig}" is already configured`);
     console.log(`   Domain folder "${domainFromConfig}" exists and is set up.`);
     console.log('   Skipping setup. If you want to re-run setup, remove the domain directory first.\n');
     return;
   }

+  // In CI/non-interactive mode, if touch doesn't exist or not configured, skip silently
+  if (isNonInteractive()) {
+    if (!fs.existsSync('touch')) {
+      return;
+    }
+    // If touch exists but we're in CI, skip silently (don't prompt)
+    return;
+  }
</code_context>

<issue_to_address>
**issue (bug_risk):** The `touch` file existence check is currently a no-op due to the unconditional return.

In the `isNonInteractive()` block, this code:

```js
if (!fs.existsSync('touch')) {
  return;
}
return;
```
returns in all cases, so the `fs.existsSync('touch')` check and its comment are misleading and effectively dead logic. If `touch` is supposed to change behavior, the second unconditional `return` needs adjusting; if not, this can be simplified to `if (isNonInteractive()) return;` to match the actual behavior.
</issue_to_address>

### Comment 2
<location> `package.json:12` </location>
<code_context>
     "sync-schema": "node sync-schema-version.js",
     "setup": "node setup.js",
-    "postinstall": "node setup.js && npm run sync-schema",
+    "postinstall": "(node setup.js || true) && npm run sync-schema",
     "prepublishOnly": "npm run sync-schema && npm run validate"
   },
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Swallowing all `setup.js` errors in `postinstall` may hide real failures.

This change makes `postinstall` always succeed even if `setup.js` fails, which can hide real configuration or environment problems on local installs. Consider only relaxing failures in non-interactive contexts (e.g., when `CI`/`GITHUB_ACTIONS` is set) or at least logging a clear warning when `setup.js` exits non‑zero so developers still see and can act on those errors.

```suggestion
    "postinstall": "node setup.js || (if [ -n \"$CI\" ] || [ -n \"$GITHUB_ACTIONS\" ]; then echo '[postinstall] Warning: setup.js failed; continuing because CI/GITHUB_ACTIONS is set' >&2; else exit 1; fi) && npm run sync-schema",
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +243 to 252
if (isNonInteractive()) {
return;
}
// In interactive mode, show message
console.log('🚀 vNext Template Setup');
console.log('=======================\n');
console.log(`✅ Domain "${domainFromConfig}" is already configured`);
console.log(` Domain folder "${domainFromConfig}" exists and is set up.`);
console.log(' Skipping setup. If you want to re-run setup, remove the domain directory first.\n');
return;
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): The touch file existence check is currently a no-op due to the unconditional return.

In the isNonInteractive() block, this code:

if (!fs.existsSync('touch')) {
  return;
}
return;

returns in all cases, so the fs.existsSync('touch') check and its comment are misleading and effectively dead logic. If touch is supposed to change behavior, the second unconditional return needs adjusting; if not, this can be simplified to if (isNonInteractive()) return; to match the actual behavior.

Copy link

@gemini-code-assist gemini-code-assist bot left a 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 aims to improve the CI workflow by making the setup script non-interactive and preventing installation failures. The changes are in the right direction, but I've found a few areas for improvement. The postinstall script change in package.json could mask legitimate errors during interactive setup. In setup.js, the logic for detecting non-interactive environments can be simplified, and the main setup function has some code duplication and convoluted logic that can be refactored for better clarity and maintainability. My detailed comments below provide specific suggestions to address these points.

"sync-schema": "node sync-schema-version.js",
"setup": "node setup.js",
"postinstall": "node setup.js && npm run sync-schema",
"postinstall": "(node setup.js || true) && npm run sync-schema",

Choose a reason for hiding this comment

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

high

The use of || true will suppress any exit code from setup.js, causing the postinstall step to always appear successful even if the setup fails for a legitimate reason (e.g., an invalid domain name provided by a user in an interactive session). This can be misleading as it hides failures. Since setup.js is being modified to exit gracefully in non-interactive environments, this error suppression might not be necessary and could be detrimental in interactive environments. Consider removing || true and ensuring setup.js has the correct exit behavior for all scenarios.

Suggested change
"postinstall": "(node setup.js || true) && npm run sync-schema",
"postinstall": "node setup.js && npm run sync-schema",

Comment on lines +190 to +194
return !process.stdin.isTTY ||
process.env.CI === 'true' ||
process.env.GITHUB_ACTIONS === 'true' ||
process.env.NPM_CONFIG_INTERACTIVE === 'false' ||
process.env.CI === '1';

Choose a reason for hiding this comment

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

medium

The logic for detecting a non-interactive environment can be simplified. The CI environment variable is set to 'true' in GitHub Actions, so checking for process.env.GITHUB_ACTIONS is redundant. Also, checking for CI being 'true' or '1' can be simplified to just checking for its presence, which is a common and more robust practice. This makes the code cleaner and easier to maintain.

Suggested change
return !process.stdin.isTTY ||
process.env.CI === 'true' ||
process.env.GITHUB_ACTIONS === 'true' ||
process.env.NPM_CONFIG_INTERACTIVE === 'false' ||
process.env.CI === '1';
return !process.stdin.isTTY ||
!!process.env.CI ||
process.env.NPM_CONFIG_INTERACTIVE === 'false';

Comment on lines 241 to +265
if (domainFromConfig && isDomainFolderConfigured()) {
// In CI/non-interactive mode, skip silently
if (isNonInteractive()) {
return;
}
// In interactive mode, show message
console.log('🚀 vNext Template Setup');
console.log('=======================\n');
console.log(`✅ Domain "${domainFromConfig}" is already configured`);
console.log(` Domain folder "${domainFromConfig}" exists and is set up.`);
console.log(' Skipping setup. If you want to re-run setup, remove the domain directory first.\n');
return;
}

// In CI/non-interactive mode, if touch doesn't exist or not configured, skip silently
if (isNonInteractive()) {
if (!fs.existsSync('touch')) {
return;
}
// If touch exists but we're in CI, skip silently (don't prompt)
return;
}

console.log('🚀 vNext Template Setup');
console.log('=======================\n');

Choose a reason for hiding this comment

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

medium

This section has some duplicated code and complex logic. The header is printed in two separate places, and the check for non-interactive mode is split and contains a redundant conditional. This can be refactored to be more readable and maintainable by handling the non-interactive case upfront, and then printing the header once for all interactive scenarios.

  if (isNonInteractive()) {
    // In non-interactive mode (e.g. CI), we should not perform any setup
    // or display any output. The script should exit gracefully.
    return;
  }

  // Interactive setup starts here
  console.log('🚀 vNext Template Setup');
  console.log('=======================\n');

  if (domainFromConfig && isDomainFolderConfigured()) {
    console.log(`✅ Domain "${domainFromConfig}" is already configured`);
    console.log(`   Domain folder "${domainFromConfig}" exists and is set up.`);
    console.log('   Skipping setup. If you want to re-run setup, remove the domain directory first.\n');
    return;
  }

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