Skip to content

Added recursive layout detection to v6#816

Open
sagzy wants to merge 2 commits into
mainfrom
fix/recursive-template
Open

Added recursive layout detection to v6#816
sagzy wants to merge 2 commits into
mainfrom
fix/recursive-template

Conversation

@sagzy
Copy link
Copy Markdown
Contributor

@sagzy sagzy commented May 21, 2026

ref https://linear.app/ghost/issue/BER-3133

  • Added a v6-only GS130-NO-RECURSIVE-LAYOUT rule to catch recursive {{!< ...}} template inheritance, including default.hbs self-inheritance.
  • Implemented a dedicated check that builds layout relationships from theme templates and reports direct and indirect cycles.
  • Added fixtures and tests covering the outage case, a valid inheritance case, and an indirect cycle.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

Review Change Stack

Walkthrough

This PR implements a new theme validation check GS130-NO-RECURSIVE-LAYOUT that detects recursive template layout inheritance in Ghost themes. The check parses Handlebars layout references ({{!< layoutName}}), normalizes paths, constructs a directed inheritance graph, and applies depth-first search with cycle detection. When cycles are found, it records failures with human-readable cycle paths. The rule is registered in the v6 specification as fatal, test fixtures cover self-inheritance and multi-level cycles, and test expectations are updated to reflect the new passing check.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description is directly related to the changeset, explaining the new v6 rule, implementation details, and test coverage.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title 'Added recursive layout detection to v6' is fully related to the main change and accurately summarizes the primary feature: a new v6-only validation rule for detecting recursive template layout inheritance.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/recursive-template

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.

@sagzy sagzy force-pushed the fix/recursive-template branch from 85debbc to 4ebe6a1 Compare May 21, 2026 21:10
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
test/130-template-inheritance.test.js (1)

1-46: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Replace should assertions with Vitest expect in test/130-template-inheritance.test.js.

This file uses require('should') and output.should... / failure.message.should... assertions; update them to vitest’s expect(...) style per the test guidelines.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/130-template-inheritance.test.js` around lines 1 - 46, Update the test
file to replace all "should" style assertions with Vitest "expect" assertions:
remove the require('should') line, import Vitest's expect if not global, and
change checks on output and results to expect(output).toBeValidThemeObject() (or
the appropriate custom matcher),
expect(Object.keys(output.results.fail)).toEqual([ruleCode]),
expect(output.results.fail).toEqual({}) /
expect(output.results.pass).toContain(ruleCode) as applicable, and change
failure.message.should.containEql(...) to expect(failure.message).toContain(...)
and failure.ref.should.eql('default.hbs') to
expect(failure.ref).toEqual('default.hbs'); update all uses of thisCheck,
output, failure, and ruleCode accordingly so assertions use expect(...) with
toEqual/toContain/toBe... matchers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@AGENTS.md`:
- Around line 105-114: Update the examples under "Common Test Patterns" to use
vitest's global expect assertions instead of the legacy should style: replace
the `check(...)` usage examples so that the passing test asserts the results
array with expect(theme.results.pass).toContain('GS010-PJ-REQ') (using check and
themePath to locate the theme) and the failing test asserts the specific failure
key with expect(theme.results.fail['GS010-PJ-NAME-REQ']).toBeDefined() or
toBeTruthy(); keep using the same helpers (`check`, `themePath`) and the same
result properties (`theme.results.pass`, `theme.results.fail`) but swap out
`.should.*` expressions for the equivalent `expect(...).toContain` /
`expect(...).toBeDefined` style.
- Around line 162-177: The example exported check function checkSomething is
missing the required third parameter themePath; update its signature to accept
(theme, options, themePath) and ensure it returns a Promise (make it async if
needed), and if options or themePath are unused add the appropriate
eslint-disable comment as noted in the guidelines so the linter won't complain.
- Around line 193-204: Update the test example in the
`test/XXX-check-name.test.js` snippet to use vitest's expect-style assertions
instead of the deprecated should library: keep the existing test structure and
the call to utils.testCheck(checkSomething, 'XXX-check-name/failing-case'), but
replace the old "output.results.fail['GSXXX-ERROR-CODE'].should.exist()"
assertion with a vitest expect assertion (e.g.,
expect(output.results.fail['GSXXX-ERROR-CODE']).toBeDefined() or another
appropriate expect matcher) so it matches the project's vitest examples and
style.

In `@lib/checks/130-template-inheritance.js`:
- Around line 137-154: The exported check function checkTemplateInheritance
currently is a synchronous two-arg function (checkTemplateInheritance(theme,
options)) but must follow the check-module contract: change it to an async
function with signature async function checkTemplateInheritance(theme, options,
themePath) (or equivalent arrow) so it returns a Promise that resolves to theme;
keep the existing logic intact, accept the extra themePath parameter (even if
unused) and ensure the module still exports checkTemplateInheritance so callers
receive a Promise.

---

Outside diff comments:
In `@test/130-template-inheritance.test.js`:
- Around line 1-46: Update the test file to replace all "should" style
assertions with Vitest "expect" assertions: remove the require('should') line,
import Vitest's expect if not global, and change checks on output and results to
expect(output).toBeValidThemeObject() (or the appropriate custom matcher),
expect(Object.keys(output.results.fail)).toEqual([ruleCode]),
expect(output.results.fail).toEqual({}) /
expect(output.results.pass).toContain(ruleCode) as applicable, and change
failure.message.should.containEql(...) to expect(failure.message).toContain(...)
and failure.ref.should.eql('default.hbs') to
expect(failure.ref).toEqual('default.hbs'); update all uses of thisCheck,
output, failure, and ruleCode accordingly so assertions use expect(...) with
toEqual/toContain/toBe... matchers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f4b0a8b8-a43b-4a7c-bcec-3e8457482a6e

📥 Commits

Reviewing files that changed from the base of the PR and between b3bec0f and 85debbc.

📒 Files selected for processing (10)
  • AGENTS.md
  • lib/checks/130-template-inheritance.js
  • lib/specs/v6.js
  • test/130-template-inheritance.test.js
  • test/checker.test.js
  • test/fixtures/themes/130-template-inheritance/indirect-cycle/default.hbs
  • test/fixtures/themes/130-template-inheritance/indirect-cycle/layouts/base.hbs
  • test/fixtures/themes/130-template-inheritance/recursive-default/default.hbs
  • test/fixtures/themes/130-template-inheritance/valid-default/default.hbs
  • test/fixtures/themes/130-template-inheritance/valid-default/index.hbs

Comment thread AGENTS.md Outdated
Comment thread AGENTS.md Outdated
Comment thread AGENTS.md Outdated
Comment thread lib/checks/130-template-inheritance.js
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 85debbc2a6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/checks/130-template-inheritance.js Outdated
@sagzy sagzy force-pushed the fix/recursive-template branch from 4ebe6a1 to 59acb95 Compare May 21, 2026 21:15
@sagzy sagzy changed the title Add v6 recursive layout detection to gscan Added recursive layout detection to v6 May 21, 2026
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.

1 participant