Skip to content

Feature/hub sync - #1089

Open
jefeish wants to merge 46 commits into
github-community-projects:yadhav/fix-recent-issuesfrom
jefeish:feature/hub-sync
Open

jefeish wants to merge 46 commits into
github-community-projects:yadhav/fix-recent-issuesfrom
jefeish:feature/hub-sync

Conversation

@jefeish

@jefeish jefeish commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

No description provided.

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Unauthenticated mutation routes, unmerged-PR propagation, broken defaults, and nonfunctional enrichment must be resolved before approval.

Review effort: Balanced
Findings: 8 High severity · 16 Medium severity · 2 Low severity

Open (26)

And 6 more that still need to be addressed.

What changed in this PR

Adds hub-and-spoke synchronization, a static dashboard, tech-asset enrichment, supporting APIs, tests, and documentation.

Changes:

  • Adds hub synchronization, installation caching, import routes, and configuration.
  • Introduces a Next.js dashboard for organizations, logs, configuration, and status.
  • Adds tech-asset enrichment through a plugin and GitHub Actions workflow.
File Description
ui/​src/​app/​utils/​basePath.js Adds URL-prefix handling.
ui/​src/​app/​not-found.jsx Adds a 404 page.
ui/​src/​app/​layout.jsx Defines root layout and metadata.
ui/​src/​app/​hooks/​useHydrated.js Adds hydration-state hook.
ui/​src/​app/​hooks/​useClientSafe.js Adds client-safe formatting hooks.
ui/​src/​app/​globals.css Adds global theme styles.
ui/​src/​app/​dashboard/​safe-settings-hub/​page.jsx Adds hub-content page.
ui/​src/​app/​dashboard/​page.jsx Adds dashboard landing page.
ui/​src/​app/​dashboard/​organizations/​page.jsx Adds organizations page.
ui/​src/​app/​dashboard/​logs/​page.jsx Adds log viewer.
ui/​src/​app/​dashboard/​help/​page.jsx Adds help page.
ui/​src/​app/​dashboard/​env/​page.jsx Adds environment page.
ui/​src/​app/​components/​TitleBar.jsx Adds dashboard navigation.
ui/​src/​app/​components/​TitleBar.css Styles navigation and header.
ui/​src/​app/​components/​ThemeToggle.jsx Adds theme-toggle control.
ui/​src/​app/​components/​ThemeContext.jsx Adds persistent theme context.
ui/​src/​app/​components/​HubOrgGraph.jsx Visualizes hub organizations.
ui/​src/​app/​components/​EnvVariables.jsx Displays environment settings.
ui/​src/​app/​api/​logs/​route.js Adds static-export log response.
ui/​src/​app/​[slug]/​route.js Adds example static route.
ui/​shield.svg Adds shield artwork.
ui/​README.md Documents UI setup.
ui/​public/​favicon.svg Adds SVG favicon.
ui/​public/​favicon.ico Adds ICO favicon.
ui/​package.json Defines UI dependencies and scripts.
ui/​next.config.js Configures static export and base path.
ui/​favicon.svg Adds alternate favicon asset.
ui/​.gitignore Adds UI ignore rules.
ui/​.eslintrc.json Configures Next.js linting.
test/​unit/​lib/​settings.test.js Reformats settings tests.
test/​unit/​lib/​routes.test.js Adds route tests.
test/​unit/​lib/​plugins/​rulesets.test.js Reformats ruleset tests.
test/​unit/​lib/​plugins/​environments.test.js Reformats environment tests.
test/​unit/​lib/​mergeConfigs.test.js Tests hub configuration merging.
test/​unit/​index.test.js Adds hub-handler mocking.
TECH_ASSET_ENRICHMENT_GUIDE.md Documents enrichment approaches.
safe-settings.log Adds a runtime log artifact.
package.json Adds hub/UI dependencies.
lib/​utils.js No textual change supplied.
lib/​settings.js Integrates enrichment processing.
lib/​plugins/​tech_asset_enrichment.js Implements enrichment plugin.
lib/​plugins/​overrides.js Applies style cleanup.
lib/​plugins/​environments.js Simplifies object construction.
lib/​mergeDeep.js Documents deep-merge behavior.
lib/​installationCache.js Adds installation caching.
lib/​env.js Adds hub environment configuration.
lib/​configManager.js Handles missing API responses.
index.js Wires routes, cache, and hub events.
examples/​smart-merge-example.js Demonstrates smart merging.
examples/​repo-with-tech-asset.yml Provides enrichment example.
examples/​merge-configs-example.js Demonstrates merge modes.
docs/​tech-asset-enrichment.md Documents enrichment plugin.
docs/​hubSyncHandler/​usecase-merge-behavior.md Starts merge-use-case documentation.
docs/​hubSyncHandler/​README.md Documents hub synchronization.
docs/​hubSyncHandler/​IMPLEMENTATION-SUMMARY.md Summarizes manifest implementation.
docs/​hubSyncHandler/​BASE_PATH.md Documents URL prefixes.
docs/​hubSyncHandler/​architecture-sequence.md Documents synchronization flows.
docs/​hubSyncHandler/​ADR-reimport_control.md Proposes reimport controls.
docs/​hubSyncHandler/​ADR-manifest-control.md Records manifest decisions.
docs/​dry-runs.md Documents dry-run behavior.
.gitignore Ignores log files.
.github/​workflows/​enrich-tech-assets.yml Adds enrichment workflow.
.github/​workflows/​advanced-codeql.yml Cleans workflow formatting.
.github/​scripts/​enrich-tech-assets.js Implements workflow enrichment.
.env.example Documents hub environment variables.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/scripts/enrich-tech-assets.js Outdated
Comment thread index.js Outdated
let appSlug = 'safe-settings'

// Initialize all routes (static UI + API) via centralized module
setupRoutes(robot, getRouter)
Comment thread index.js
Comment thread lib/plugins/tech_asset_enrichment.js Outdated
Comment thread lib/plugins/tech_asset_enrichment.js Outdated
Comment thread ui/src/app/components/HubOrgGraph.jsx Outdated
Comment thread ui/src/app/components/TitleBar.css Outdated
Comment thread ui/src/app/utils/basePath.js Outdated
Comment thread docs/hubSyncHandler/ADR-manifest-control.md Outdated
Comment thread docs/hubSyncHandler/README.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The UI configuration has a syntax error, Settings imports a missing plugin, and several routing and test regressions remain.

Review effort: Balanced
Findings: 5 High severity · 2 Medium severity

Open (7)
Resolved since last review (6)
Previously missed (3)

In code that hasn't changed since last review

Medium severity Hub repository guard omits organization check

index.js:781

Unlike the other new hub-repository guards, this one checks only the repository name. A PR opened in a same-named repository in any other organization will incorrectly create a Safe Settings validation check that the later check_run.created owner guard refuses to process. Include the configured hub organization in this predicate.

Medium severity Reopened PR hub check omits organization validation

index.js:802

This reopened-PR path also identifies the hub by repository name alone. Reopening a PR in a same-named repository outside SAFE_SETTINGS_HUB_ORG therefore creates a validation check that cannot be completed by the owner-scoped handler. Apply the same organization check used for check_suite.requested.

Medium severity Asset URLs ignore configured base path

ui/​src/​app/​layout.jsx:14

These public-asset URLs are rooted at the host, so under the configured /safe-settings (or any custom) basePath they request /favicon.* outside the mounted router and return 404. Prefix metadata and the duplicate <head> icon links with the configured base path, or use a base-path-aware file metadata approach.

Comment thread lib/settings.js Outdated
Comment thread test/unit/lib/routes.test.js Outdated
Removed tech asset enrichment plugin from settings and related code.

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Build-breaking syntax, unauthenticated mutation routes, production packaging failures, and routing inconsistencies must be resolved.

Review effort: Balanced
Findings: 7 High severity · 1 Medium severity

Open (8)
Resolved since last review (3)
Previously missed (10)

In code that hasn't changed since last review

Medium severity Restore archived tests or update the test script

test/​integration/​transport/​archived-repositories.test.js:1

Deleting this suite leaves the existing npm run test:archived script pointing to a nonexistent file, so that documented command now fails instead of running. It also silently removes these archived-repository regression cases from the integration-test glob; restore the suite or update the script and provide equivalent coverage.

Medium severity Make the success test assert a valid response

test/​unit/​lib/​routes.test.js:90

This success test accepts every plausible outcome, including HTTP 500, and only asserts that Express returned a body. Because cacheGetInstallations is not configured here, the route currently takes its error path and the test still passes. Mock a hub installation/authenticated content response and require 200 plus the expected tree; inject a distinct failure for the following error test.

Medium severity Make file selection keyboard accessible

ui/​src/​app/​components/​Safe-settings-hubContent.jsx:132

File selection is implemented as an onClick handler on a non-focusable <div>, making files impossible to select from the keyboard. Render this row as a button/treeitem with keyboard support and selected state.

This issue also appears on line 143 of the same file.

Medium severity Make content-table navigation keyboard accessible

ui/​src/​app/​components/​Safe-settings-hubContent.jsx:218

The content-table rows are clickable but not keyboard-focusable or operable, so this second navigation path is also inaccessible without a pointer. Put the item action in a link/button or add equivalent keyboard semantics.

Medium severity Fix insufficient dark-theme navigation contrast

ui/​src/​app/​globals.css:91

This !important rule forces dark-theme navigation text to #6c757d on the #22272e navigation background, which is below the WCAG 4.5:1 contrast requirement for normal text. It also overrides the higher-contrast component rule in TitleBar.css; use the dark theme's primary text color instead.

Low severity Update the link to the dry-run orchestration code

docs/​dry-runs.md:48

This anchor currently points to the repository-renamed handler (index.js:639-700), not dry-run check orchestration, which is now around index.js:747-918. Update the link so readers reach the implementation being described.

Low severity Remove stale destination files during reimport

docs/​hubSyncHandler/​ADR-reimport_control.md:219

The implementation does not replace the entire destination tree during reimport. retrieveSettingsFromOrgs() creates a Git tree with base_tree and only overlays files currently found in the source, so destination files deleted from the organization remain in the hub. Either implement deletion of stale paths or document the additive/update behavior rather than promising full replacement.

Low severity Replace absolute filesystem paths with repository links

docs/​hubSyncHandler/​IMPLEMENTATION-SUMMARY.md:216

These machine-specific absolute paths are not usable repository references and expose a contributor's local filesystem layout. Replace them with repository-relative paths/links; the same issue recurs for the entries below.

Low severity Correct the documented default configuration path

docs/​hubSyncHandler/​README.md:279

The documented default incorrectly includes CONFIG_PATH. Runtime code constructs paths as CONFIG_PATH/SAFE_SETTINGS_HUB_PATH, and lib/env.js defaults this variable to safe-settings; configuring .github/safe-settings as shown would produce .github/.github/safe-settings.

Low severity Fix the nonexistent module in the usage example

examples/​merge-configs-example.js:238

The printed usage imports a module that does not exist; this example itself imports mergeConfigs from lib/hubSyncHandler.js. Copying the summary snippet therefore fails with MODULE_NOT_FOUND.

Comment thread index.js
Comment on lines +30 to +32
if (typeof getRouter === 'function') {
setupRoutes(robot, getRouter)
}
Comment thread index.js Outdated
Comment thread package.json Outdated
Comment thread ui/src/app/[slug]/route.js Outdated

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The UI build is currently invalid, routing defaults conflict, privileged APIs lack access control, and test execution has guaranteed failures.

Review effort: Balanced
Findings: 5 High severity · 2 Medium severity

Open (7)
Resolved since last review (3)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Ensure deepMerge lets explicit null override existing values

test/​unit/​lib/​mergeConfigs.test.js:193

This new test cannot pass against the added deepMerge implementation: when the overlay value is null, deepMerge returns the existing target value, so the result is { a: 1, b: 2 }, not { a: 1, b: null }. Update the merge logic so an explicit YAML null overrides the prior value, or change the documented/tested contract consistently.

Medium severity Prefix public asset URLs with the configured base path

ui/​src/​app/​layout.jsx:14

These root-relative public-asset URLs bypass the configured Next.js basePath. Under the default /safe-settings deployment they request /favicon.* from the server root, while static assets are mounted below the prefix, so the icons return 404. Prefix all metadata and manual icon URLs with the same normalized base path.

Comment thread index.js
Comment on lines +30 to +32
if (typeof getRouter === 'function') {
setupRoutes(robot, getRouter)
}
Comment thread index.js Outdated

Copilot AI 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.

Comment thread index.js
const hubPath = `${env.CONFIG_PATH}/${env.SAFE_SETTINGS_HUB_PATH}`.replace(/\/+/g, '/')
const globalsPattern = new RegExp(`^${hubPath}/globals/.*\\.ya?ml$`)
const orgsPattern = new RegExp(`^${hubPath}/organizations/([^/]+)/.*\\.ya?ml$`)
const hubSyncFilesChanged = files.filter(f => globalsPattern.test(f) || orgsPattern.test(f))
Comment on lines +87 to +91
it('should return hub content', async () => {
const res = await request(app).get('/api/safe-settings/hub/content')
expect([200, 404, 500]).toContain(res.statusCode)
expect(res.body).toBeDefined()
})
Comment thread ui/src/app/globals.css
Comment on lines +271 to +273
.log-error {
color: #c00 !important;
}
Comment thread ui/src/app/globals.css
Comment on lines +275 to +277
.log-warn {
color: #b8860b !important;
} No newline at end of file
Comment thread ui/src/app/layout.jsx
Comment on lines +28 to +29
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" href="/favicon.ico" sizes="any" />
Comment on lines +151 to +155
# mergeStrategy: merge | overwrite | preserve
# --------------------------------------------
# merge = use a PR to sync files
# overwrite = sync all files to the target ORG(s) (no PR)
mergeStrategy: merge
Comment on lines +132 to +135
<div key={node.path} className={`d-flex align-items-center py-1 ${selected ? 'theme-bg-secondary' : ''}`} style={{ paddingLeft: depth * 12, cursor: 'pointer' }} onClick={() => setSelectedPath(node.path)}>
<FileIcon size={12} className="me-2" />
<span className="small text-truncate">{node.name}</span>
</div>

This branch has not been deployed

No deployments
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.

3 participants