From 002913c20ed8978d6575ef049caea66c467fbd98 Mon Sep 17 00:00:00 2001 From: Amaury Ricardo Date: Wed, 1 Jul 2026 14:42:58 -0300 Subject: [PATCH 01/10] feat(cr): add pre-push hook --- .pushgate.yml | 190 ++++++++++++++++++++++++++++++++++++++++++++++ README-project.md | 23 ++++++ README.md | 23 ++++++ 3 files changed, 236 insertions(+) create mode 100644 .pushgate.yml diff --git a/.pushgate.yml b/.pushgate.yml new file mode 100644 index 000000000..bc02c1aa6 --- /dev/null +++ b/.pushgate.yml @@ -0,0 +1,190 @@ +# ============================================================================= +# Pushgate v2 configuration - full reference +# https://github.com/rootstrap/ai-pushgate +# ============================================================================= +# Commit .pushgate.yml so the team shares review settings. +# +# To install or update Pushgate: +# curl -fsSL https://raw.githubusercontent.com/rootstrap/ai-pushgate/main/install.sh | bash +# +# Reinstall with a pre-built template when useful: +# curl -fsSL https://raw.githubusercontent.com/rootstrap/ai-pushgate/main/install.sh | bash -s -- --template node +# curl -fsSL https://raw.githubusercontent.com/rootstrap/ai-pushgate/main/install.sh | bash -s -- --template typescript +# curl -fsSL https://raw.githubusercontent.com/rootstrap/ai-pushgate/main/install.sh | bash -s -- --template nextjs +# curl -fsSL https://raw.githubusercontent.com/rootstrap/ai-pushgate/main/install.sh | bash -s -- --template ruby +# curl -fsSL https://raw.githubusercontent.com/rootstrap/ai-pushgate/main/install.sh | bash -s -- --template rails +# ============================================================================= + +version: 2 + +ai: + # Supported modes: blocking, advisory, off. + mode: advisory + + # Changed-line overages block the push; prompt-token overages skip local AI. + max_changed_lines: 500 + max_prompt_tokens: 12000 + timeout_seconds: 120 + + # Blocking and advisory modes select a provider and define its matching block. + provider: claude + providers: + # Provider-specific settings are kept below the provider name. + claude: + model: claude-sonnet-4-20250514 + # To use the standalone GitHub Copilot CLI, set provider: copilot and + # uncomment this block. Omit model to let Copilot choose its default. + # copilot: + # model: auto + +review: + # Branch to diff against when collecting changes. + target_branch: master + + # Lines of surrounding context included in the diff sent to the provider. + context_lines: 10 + + # Below this changed-line threshold, later AI work can send full file context. + max_lines_for_full_file: 300 + +# ============================================================================= +# Tools +# ============================================================================= +# Tools run before AI review. Each command is an argv array, not a shell string. +# A {changed_files} token expands to individual argv entries without shell +# interpolation, so filenames with spaces stay one argument. +# +# Tool defaults: +# timeout_seconds: 60 +# mode: blocking # blocking | warning; warnings require confirmation +# run: changed_files # changed_files | always +# fail_fast: true +# +# Examples (uncomment and adapt as needed): +# +# tools: +# - name: eslint +# command: ["npx", "eslint", "{changed_files}"] +# extensions: [".js", ".jsx", ".ts", ".tsx", ".mjs"] +# timeout_seconds: 60 +# mode: blocking +# run: changed_files +# fail_fast: true +# +# - name: prettier +# command: ["npx", "prettier", "--check", "{changed_files}"] +# extensions: [".js", ".jsx", ".ts", ".tsx", ".mjs", ".json", ".css", ".md"] +# +# - name: rubocop +# command: ["bundle", "exec", "rubocop", "{changed_files}"] +# extensions: [".rb", ".rake", ".gemspec"] +# +# - name: brakeman +# command: ["bundle", "exec", "brakeman", "--no-pager"] +# run: always +# +# - name: pytest +# command: ["pytest", "--tb=short"] +# extensions: [".py"] +# +tools: + - name: type-check + command: ["pnpm", "run", "type-check"] + run: always + timeout_seconds: 120 + mode: blocking + fail_fast: true + + - name: lint + command: ["pnpm", "run", "lint"] + run: always + timeout_seconds: 120 + mode: blocking + fail_fast: true + + - name: lint-translations + command: ["pnpm", "run", "lint:translations"] + run: always + timeout_seconds: 120 + mode: blocking + fail_fast: true + +# ============================================================================= +# Built-in deterministic policies +# ============================================================================= +# Built-ins are opt-in local checks that do not require external tools. +# +# Policy defaults: +# mode: blocking # blocking | warning; warnings require confirmation +# +# Examples (uncomment and adapt as needed): +# +# policies: +# diff_size: +# max_changed_lines: 500 +# mode: warning # asks before continuing +# fail_fast: false # if blocking, continue later checks after a violation +# +# forbidden_paths: +# patterns: +# - ".env" +# - ".env.*" +# - "secrets/**" +# - "*.pem" +# mode: blocking +# fail_fast: true +# +policies: + diff_size: + max_changed_lines: 500 + mode: warning + fail_fast: false + + forbidden_paths: + patterns: + - ".env" + - ".env.*" + - "secrets/**" + - "*.pem" + mode: blocking + fail_fast: true + +# ============================================================================= +# Plugins +# ============================================================================= +# Plugin adapters run external scanners through a first-class Pushgate result +# model. They run after built-in policies and before generic tools. +# +# Gitleaks scans the branch commit range for secrets before push. Install it +# separately (for example, brew install gitleaks) and tune rules with +# .gitleaks.toml, .gitleaksignore, or a baseline report. +# +# plugins: +# gitleaks: +# enabled: true +# command: gitleaks +# timeout_seconds: 60 +# mode: blocking +# fail_fast: true +# config_path: .gitleaks.toml +# baseline_path: .gitleaks/baseline.json +# gitleaks_ignore_path: .gitleaksignore +# +plugins: {} + +# ============================================================================= +# Ignore paths +# ============================================================================= +# Files and patterns excluded from tool checks and AI review. +ignore_paths: + - "*.lock" + - "package-lock.json" + - "pnpm-lock.yaml" + - "yarn.lock" + - "Gemfile.lock" + - "dist/**" + - "build/**" + - ".next/**" + - "coverage/**" + - "tmp/**" + - "log/**" diff --git a/README-project.md b/README-project.md index becde97db..417679f32 100644 --- a/README-project.md +++ b/README-project.md @@ -59,6 +59,29 @@ To build your app locally you can run any of the build scripts with --local. `pnpm build:development:ios --local` +## Pushgate + +This repository uses `ai-pushgate` from `.git/hooks/pre-push` to run local checks before `git push`. + +Pushgate setup for template users: +- `.pushgate.yml` is versioned, so everyone gets the same rules. +- `.git/hooks/pre-push` is local and is not committed to Git. +- Each developer must install Pushgate once per clone. + +Install from repo root: +```sh +curl -fsSL https://raw.githubusercontent.com/rootstrap/ai-pushgate/main/install.sh | bash +``` + +Verify the hook was created: +```sh +ls .git/hooks/pre-push +``` + +How to skip checks: +> Skip AI only: `git -c pushgate.skip-ai-check=true push` +> Skip everything: `git push --no-verify` + ### SonarQube setup SonarQube is an open-source platform for continuous inspection of code quality. It performs automatic reviews to detect bugs, code smells, and security vulnerabilities. Rootstrap has a SonarQube instance to improve the quality of the software we develop. On each PR, a GitHub Action is triggered to perform the analysis. To set up SonarQube correctly, you need to add the `SONAR_TOKEN`, `SONAR_URL`, and `SONAR_PROJECT` secrets to the repository. Additionally, you must select the quality gate named `ReactNativeTemplate` for your project on SonarQube. In case you're using this project outside Rootstrap and you're not planning to use SonarQube the sonar scanner [workflow](.github/workflows/sonar.yml) should be deleted. diff --git a/README.md b/README.md index a93fddb37..36266dcb3 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,29 @@ The bot will be triggered on issues, pull requests and comments, you can modify Check this [file](https://github.com/rootstrap/rs-gpt-review/blob/main/.github/workflows/main.yml) for more examples. +## Pushgate + +This repository uses `ai-pushgate` from `.git/hooks/pre-push` to run local checks before `git push`. + +Pushgate setup for template users: +- `.pushgate.yml` is versioned, so everyone gets the same rules. +- `.git/hooks/pre-push` is local and is not committed to Git. +- Each developer must install Pushgate once per clone. + +Install from repo root: +```sh +curl -fsSL https://raw.githubusercontent.com/rootstrap/ai-pushgate/main/install.sh | bash +``` + +Verify the hook was created: +```sh +ls .git/hooks/pre-push +``` + +How to skip checks: +> Skip AI only: `git -c pushgate.skip-ai-check=true push` +> Skip everything: `git push --no-verify` + ## πŸ’Ž Libraries used From 6cf7fead91fcc95d44d4bb2745e3a4a3a4fca967 Mon Sep 17 00:00:00 2001 From: Amaury Ricardo Date: Wed, 1 Jul 2026 15:06:56 -0300 Subject: [PATCH 02/10] feat(cr): install pre-push tool in the installation cli --- README-project.md | 3 ++- README.md | 3 ++- cli/index.js | 9 ++++++++- cli/setup-project.js | 17 +++++++++++++++-- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/README-project.md b/README-project.md index 417679f32..607205b1e 100644 --- a/README-project.md +++ b/README-project.md @@ -66,7 +66,8 @@ This repository uses `ai-pushgate` from `.git/hooks/pre-push` to run local check Pushgate setup for template users: - `.pushgate.yml` is versioned, so everyone gets the same rules. - `.git/hooks/pre-push` is local and is not committed to Git. -- Each developer must install Pushgate once per clone. +- If you create the app with `create-rootstrap-rn-app`, Pushgate is installed automatically during setup. +- For existing clones, or if the hook is missing, install it manually: Install from repo root: ```sh diff --git a/README.md b/README.md index 36266dcb3..30b777574 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,8 @@ This repository uses `ai-pushgate` from `.git/hooks/pre-push` to run local check Pushgate setup for template users: - `.pushgate.yml` is versioned, so everyone gets the same rules. - `.git/hooks/pre-push` is local and is not committed to Git. -- Each developer must install Pushgate once per clone. +- If you create the app with `create-rootstrap-rn-app`, Pushgate is installed automatically during setup. +- For existing clones, or if the hook is missing, install it manually: Install from repo root: ```sh diff --git a/cli/index.js b/cli/index.js index 2d3bd1d36..35f2bc4c0 100755 --- a/cli/index.js +++ b/cli/index.js @@ -3,7 +3,11 @@ const { consola } = require('consola'); const { showMoreDetails } = require('./utils.js'); const { cloneLatestTemplateRelease } = require('./clone-repo.js'); -const { setupProject, installDependencies } = require('./setup-project.js'); +const { + setupProject, + installDependencies, + installPushgate, +} = require('./setup-project.js'); const pkg = require('./package.json'); const { name: packageName } = pkg; @@ -27,6 +31,9 @@ const createRootstrapApp = async () => { // install project dependencies using pnpm await installDependencies(projectName); + // install Pushgate hook (best-effort) + await installPushgate(projectName); + // show instructions to run the project + link to the documentation showMoreDetails(projectName); }; diff --git a/cli/setup-project.js b/cli/setup-project.js index cbde3776b..5cc0c70f0 100755 --- a/cli/setup-project.js +++ b/cli/setup-project.js @@ -1,8 +1,6 @@ const { execShellCommand, runCommand, - UPSTREAM_REPOSITORY, - TEMPLATE_REPOSITORY, } = require('./utils.js'); const { consola } = require('consola'); const fs = require('fs-extra'); @@ -25,6 +23,20 @@ const installDependencies = async (projectName) => { }); }; +const installPushgate = async (projectName) => { + consola.start('Installing Pushgate pre-push hook'); + try { + await execShellCommand( + `cd ${projectName} && curl -fsSL https://raw.githubusercontent.com/rootstrap/ai-pushgate/main/install.sh | bash` + ); + consola.success('Pushgate pre-push hook installed'); + } catch (error) { + consola.warn( + 'Could not auto-install Pushgate. Run installer manually from the project root.' + ); + } +}; + const removeUnrelatedFiles = () => { projectFilesManager.removeFiles([ '.git', @@ -227,4 +239,5 @@ const setupProject = async (projectName) => { module.exports = { setupProject, installDependencies, + installPushgate, }; From 9746e581a2c1c9caef6cfc8e9abcd0e87aec3726 Mon Sep 17 00:00:00 2001 From: Amaury Ricardo Date: Wed, 1 Jul 2026 15:24:29 -0300 Subject: [PATCH 03/10] feat(pushgate): add eslint and test tools --- .pushgate.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.pushgate.yml b/.pushgate.yml index bc02c1aa6..d03b3ec67 100644 --- a/.pushgate.yml +++ b/.pushgate.yml @@ -95,6 +95,14 @@ tools: mode: blocking fail_fast: true + - name: eslint + command: ["pnpm", "exec", "eslint", "{changed_files}"] + extensions: [".js", ".jsx", ".ts", ".tsx", ".mjs"] + run: changed_files + timeout_seconds: 120 + mode: blocking + fail_fast: true + - name: lint command: ["pnpm", "run", "lint"] run: always @@ -109,6 +117,13 @@ tools: mode: blocking fail_fast: true + - name: test + command: ["pnpm", "run", "test"] + run: always + timeout_seconds: 120 + mode: blocking + fail_fast: true + # ============================================================================= # Built-in deterministic policies # ============================================================================= From b653099386f775ecb72b035bcd12a15db491769f Mon Sep 17 00:00:00 2001 From: Amaury Ricardo Date: Wed, 1 Jul 2026 15:29:53 -0300 Subject: [PATCH 04/10] feat(skill): update cr description to add risk labels --- .agents/skills/pr-description/SKILL.md | 10 ++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 19 +++++++++++++++++++ README-project.md | 17 +++++++++++++++++ README.md | 17 +++++++++++++++++ 4 files changed, 63 insertions(+) diff --git a/.agents/skills/pr-description/SKILL.md b/.agents/skills/pr-description/SKILL.md index f9b0fac9c..c6486c782 100644 --- a/.agents/skills/pr-description/SKILL.md +++ b/.agents/skills/pr-description/SKILL.md @@ -62,6 +62,16 @@ Write 1-3 concise sentences explaining the reason for the change. Tie it to the Name affected screens, flows, platforms, users, modules, or developer workflows. Use a short sentence or compact bullets. If impact is unclear, leave a placeholder comment instead of guessing. +### Risk Classification + +Add the appropriate `risk:*` label when the PR is opened. If the label is unknown, escalate instead of guessing. + +- `risk:low` for config, copy, or minor UI tweaks with low blast radius. +- `risk:medium` for feature work or refactors touching multiple files. +- `risk:high` for auth, payments, migrations, or security-sensitive code. + +If the branch or user request does not make the risk obvious, leave the template placeholder and call out the uncertainty in Notes. + ### How did you test this? List commands run and manual checks performed. Keep the existing checklist from the template and check only items that are supported by evidence or explicitly provided by the user. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a0878d3de..bfe6fc5da 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -35,6 +35,25 @@ _**Why** did you make these changes? This is your opportunity to provide the rat _Does your code affect something downstream? Are there side effects people should know about? Tag any developers that should be kept abreast of this change._ --> +--- + +### Layer 2: Risk Classification + +Author applies a risk label when opening the PR. When in doubt, escalate. + +| Label | When to use | +| --- | --- | +| `risk:low` | Config, copy, minor UI tweaks. Low blast radius. | +| `risk:medium` | Feature work, refactors touching multiple files. | +| `risk:high` | Auth, payments, migrations, security-sensitive code. | + +**Setup** + +- [ ] Create `risk:low`, `risk:medium`, `risk:high` labels in the repo +- [ ] Add risk criteria to contributing guide or PR template +- [ ] Add reminder in PR template to apply the label before requesting review +- [ ] Define who can override/escalate (suggested: tech lead) + ## How did you test this? ## πŸ’Ž Libraries used diff --git a/cli/clone-repo.js b/cli/clone-repo.js index 269d4e0a2..e9daa0a07 100755 --- a/cli/clone-repo.js +++ b/cli/clone-repo.js @@ -1,4 +1,8 @@ -const { runCommand, TEMPLATE_REPOSITORY } = require('./utils.js'); +const { + runCommand, + TEMPLATE_REPOSITORY, + escapeShellArg, +} = require('./utils.js'); const { consola } = require('consola'); const getLatestRelease = async () => { @@ -23,7 +27,9 @@ const cloneLatestTemplateRelease = async (projectName) => { consola.info(`Using Rootstrap's Template ${latestRelease}`); // create a new project based on Rootstrap template - const cloneStarter = `git clone -b ${latestRelease} --depth=1 https://github.com/${TEMPLATE_REPOSITORY}.git ${projectName}`; + const escapedLatestRelease = escapeShellArg(latestRelease); + const escapedProjectName = escapeShellArg(projectName); + const cloneStarter = `git clone -b ${escapedLatestRelease} --depth=1 https://github.com/${TEMPLATE_REPOSITORY}.git ${escapedProjectName}`; await runCommand(cloneStarter, { loading: 'Extracting the template...', success: 'Template extracted successfully', diff --git a/cli/setup-project.js b/cli/setup-project.js index 5cc0c70f0..e4b6f42ab 100755 --- a/cli/setup-project.js +++ b/cli/setup-project.js @@ -1,6 +1,7 @@ const { execShellCommand, runCommand, + escapeShellArg, } = require('./utils.js'); const { consola } = require('consola'); const fs = require('fs-extra'); @@ -12,11 +13,13 @@ const ProjectFilesManager = require('./project-files-manager.js'); let projectFilesManager; const initializeProjectRepository = async (projectName) => { - await execShellCommand(`cd ${projectName} && git init && cd ..`); + const escapedProjectName = escapeShellArg(projectName); + await execShellCommand(`cd ${escapedProjectName} && git init && cd ..`); }; const installDependencies = async (projectName) => { - await runCommand(`cd ${projectName} && pnpm install`, { + const escapedProjectName = escapeShellArg(projectName); + await runCommand(`cd ${escapedProjectName} && pnpm install`, { loading: 'Installing project dependencies', success: 'Dependencies installed', error: 'Failed to install dependencies, Make sure you have pnpm installed', @@ -26,8 +29,9 @@ const installDependencies = async (projectName) => { const installPushgate = async (projectName) => { consola.start('Installing Pushgate pre-push hook'); try { + const escapedProjectName = escapeShellArg(projectName); await execShellCommand( - `cd ${projectName} && curl -fsSL https://raw.githubusercontent.com/rootstrap/ai-pushgate/main/install.sh | bash` + `cd ${escapedProjectName} && curl -fsSL https://raw.githubusercontent.com/rootstrap/ai-pushgate/main/install.sh | bash` ); consola.success('Pushgate pre-push hook installed'); } catch (error) { diff --git a/cli/utils.js b/cli/utils.js index 7bbcb5e1d..1b336c095 100755 --- a/cli/utils.js +++ b/cli/utils.js @@ -5,6 +5,10 @@ const { consola } = require('consola'); const UPSTREAM_REPOSITORY = "obytes/react-native-template-obytes"; const TEMPLATE_REPOSITORY = "rootstrap/react-native-template"; +const escapeShellArg = (value) => { + return `'${String(value).replace(/'/g, "'\\''")}'`; +}; + const execShellCommand = (cmd) => { return new Promise((resolve, reject) => { exec(cmd, (error, stdout, stderr) => { @@ -46,6 +50,7 @@ module.exports = { runCommand, showMoreDetails, execShellCommand, + escapeShellArg, UPSTREAM_REPOSITORY, TEMPLATE_REPOSITORY, }; From 5c8948ae2469d888812aa9f71a5ff54f5b69539d Mon Sep 17 00:00:00 2001 From: Amaury Ricardo Date: Wed, 8 Jul 2026 09:49:11 -0300 Subject: [PATCH 09/10] feat(cr): run local review --- .agents/skills/review-changes/SKILL.md | 45 ++++++++++++++++++++++---- .claude/skills/review-changes/SKILL.md | 45 ++++++++++++++++++++++---- .husky/pre-push | 4 +-- 3 files changed, 80 insertions(+), 14 deletions(-) diff --git a/.agents/skills/review-changes/SKILL.md b/.agents/skills/review-changes/SKILL.md index 3130a8276..44f18e3fd 100644 --- a/.agents/skills/review-changes/SKILL.md +++ b/.agents/skills/review-changes/SKILL.md @@ -56,16 +56,49 @@ Perform a code review of the current branch diff against the project's architect ## Output Format -Group findings by REVIEW.md category. For each finding: +Start with an overall classification, then list findings grouped by REVIEW.md category. + +### Required Labels + +Every finding must start with exactly one label: +- `ai:clean` β€” no significant issues found. +- `ai:minor` β€” style/readability/maintainability/convention issues unlikely to cause bugs. +- `ai:serious` β€” logic/security/correctness/reliability issues that should block merge. + +Overall review classification must use the highest severity found: +- If any finding is `ai:serious`, overall is `ai:serious`. +- Else if any finding is `ai:minor`, overall is `ai:minor`. +- Else overall is `ai:clean`. + +### Report Structure + +1. Overall summary block: ``` -**[Category]** `path/to/file.ts` β€” short description of the issue and what the correct approach is. +Overall Review: ai: + +Summary: +- +- ``` -If a category has no issues, skip it. +2. Findings grouped by category. For each finding: -End the report with one of: -- **No issues found** β€” if the diff is clean across all categories. -- **X issue(s) found** β€” a one-line summary count. +``` +ai: **[Category]** `path/to/file.ts:line` β€” short description of the issue and what the correct approach is. +``` + +If a category has no findings, skip it. + +If no issues are found, output a single clean finding plus a clean overall summary: + +``` +Overall Review: ai:clean + +Summary: +- No significant issues found. + +ai:clean Review passed with no actionable findings. +``` Do not suggest stylistic preferences not grounded in REVIEW.md, AGENTS.md, or agent_docs/. Do not flag things that are already handled automatically by the interceptors or tooling (e.g. case conversion, token injection). diff --git a/.claude/skills/review-changes/SKILL.md b/.claude/skills/review-changes/SKILL.md index 3130a8276..44f18e3fd 100644 --- a/.claude/skills/review-changes/SKILL.md +++ b/.claude/skills/review-changes/SKILL.md @@ -56,16 +56,49 @@ Perform a code review of the current branch diff against the project's architect ## Output Format -Group findings by REVIEW.md category. For each finding: +Start with an overall classification, then list findings grouped by REVIEW.md category. + +### Required Labels + +Every finding must start with exactly one label: +- `ai:clean` β€” no significant issues found. +- `ai:minor` β€” style/readability/maintainability/convention issues unlikely to cause bugs. +- `ai:serious` β€” logic/security/correctness/reliability issues that should block merge. + +Overall review classification must use the highest severity found: +- If any finding is `ai:serious`, overall is `ai:serious`. +- Else if any finding is `ai:minor`, overall is `ai:minor`. +- Else overall is `ai:clean`. + +### Report Structure + +1. Overall summary block: ``` -**[Category]** `path/to/file.ts` β€” short description of the issue and what the correct approach is. +Overall Review: ai: + +Summary: +- +- ``` -If a category has no issues, skip it. +2. Findings grouped by category. For each finding: -End the report with one of: -- **No issues found** β€” if the diff is clean across all categories. -- **X issue(s) found** β€” a one-line summary count. +``` +ai: **[Category]** `path/to/file.ts:line` β€” short description of the issue and what the correct approach is. +``` + +If a category has no findings, skip it. + +If no issues are found, output a single clean finding plus a clean overall summary: + +``` +Overall Review: ai:clean + +Summary: +- No significant issues found. + +ai:clean Review passed with no actionable findings. +``` Do not suggest stylistic preferences not grounded in REVIEW.md, AGENTS.md, or agent_docs/. Do not flag things that are already handled automatically by the interceptors or tooling (e.g. case conversion, token injection). diff --git a/.husky/pre-push b/.husky/pre-push index c397b3dad..5e96612d1 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -29,6 +29,6 @@ if command_exists pushgate; then exit $? fi -echo '>> Pushgate runner not found; skipping pre-push checks.' +echo '>> Pushgate runner not found; failing push to avoid bypassing required checks.' echo '>> Install with: curl -fsSL https://raw.githubusercontent.com/rootstrap/ai-pushgate/main/install.sh | bash' -exit 0 \ No newline at end of file +exit 1 \ No newline at end of file From be5477891463ec16c833c96c206dcbb281015f79 Mon Sep 17 00:00:00 2001 From: Amaury Ricardo Date: Wed, 8 Jul 2026 10:10:26 -0300 Subject: [PATCH 10/10] feat(cr): fix sonar suggestion --- cli/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/utils.js b/cli/utils.js index 1b336c095..d72704b4a 100755 --- a/cli/utils.js +++ b/cli/utils.js @@ -6,7 +6,7 @@ const UPSTREAM_REPOSITORY = "obytes/react-native-template-obytes"; const TEMPLATE_REPOSITORY = "rootstrap/react-native-template"; const escapeShellArg = (value) => { - return `'${String(value).replace(/'/g, "'\\''")}'`; + return `'${String(value).replaceAll(/'/g, "'\\''")}'`; }; const execShellCommand = (cmd) => {