Skip to content

Conversation

@maor-rozenfeld
Copy link
Contributor

Resolves OPS-3284.

Copilot AI review requested due to automatic review settings January 6, 2026 11:43
@linear
Copy link

linear bot commented Jan 6, 2026

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces the ability to disable analytics functionality in the application by adding a new OPS_ANALYTICS_ENABLED environment variable that defaults to true. When set to false, analytics-related features are conditionally skipped.

  • Adds ANALYTICS_ENABLED system property with a default value of true
  • Conditionally registers analytics routes, seeds, and UI components based on the flag
  • Updates configuration files to include the new environment variable

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/server/shared/src/lib/system/system-prop.ts Adds ANALYTICS_ENABLED enum value to AppSystemProp
packages/server/shared/src/lib/system/system.ts Adds default value for ANALYTICS_ENABLED and implements isAnalyticsEnabled() helper
packages/server/shared/test/system/system.test.ts Adds test coverage for the new isAnalyticsEnabled() function
packages/server/api/src/main.ts Conditionally executes analytics seeding based on the enabled flag
packages/server/api/src/app/flags/flag.service.ts Returns undefined for analytics public URL when analytics are disabled
packages/server/api/src/app/database/seeds/openops-analytics-seed.ts Adds early return guard for disabled analytics
packages/server/api/src/app/authentication/authentication.controller.ts Conditionally registers analytics routes only when enabled
packages/server/api/src/app/ai/mcp/tools-initializer.ts Checks analytics enabled status before loading Superset tools
packages/server/api/src/app/ai/mcp/superset-tools.ts Returns empty toolset when analytics are disabled
packages/server/api/test/unit/authentication/authentication.controller.test.ts Adds tests verifying analytics routes are conditionally registered
packages/server/api/tsconfig.spec.json Adds @fastify/cookie type declaration
packages/server/api/.env.tests Sets OPS_ANALYTICS_ENABLED=true for test environment
packages/react-ui/src/app/router.tsx Conditionally adds analytics route based on public URL flag
packages/react-ui/src/app/features/navigation/lib/menu-links-hook.ts Conditionally includes analytics menu link when public URL is available
deploy/helm/openops/values.yaml Adds OPS_ANALYTICS_ENABLED: "true" to Helm values
deploy/helm/openops/values.overrides-example.yaml Includes example override for analytics enabled flag
deploy/docker-compose/.env.defaults Sets default value for OPS_ANALYTICS_ENABLED
.env.template Documents the new OPS_ANALYTICS_ENABLED environment variable

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI commented Jan 6, 2026

@maor-rozenfeld I've opened a new pull request, #1803, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Jan 6, 2026

@maor-rozenfeld I've opened a new pull request, #1804, to work on those changes. Once the pull request is ready, I'll request review from you.

maor-rozenfeld and others added 5 commits January 6, 2026 12:53
The analytics test in `system.test.ts` modifies
`process.env['OPS_ANALYTICS_ENABLED']` but doesn't restore it, causing
potential test pollution.

## Additional Notes

Wrapped test assertions in try/finally block to guarantee cleanup even
on assertion failure. Maintains consistency with existing
`Reflect.deleteProperty` usage in the file's `beforeEach` hook.

```typescript
it('enables analytics by default and respects disabling flag', () => {
  const originalAnalyticsEnabled = process.env['OPS_ANALYTICS_ENABLED'];

  try {
    expect(system.isAnalyticsEnabled()).toBe(true);

    process.env['OPS_ANALYTICS_ENABLED'] = 'false';
    expect(system.isAnalyticsEnabled()).toBe(false);
  } finally {
    if (originalAnalyticsEnabled === undefined) {
      Reflect.deleteProperty(process.env, 'OPS_ANALYTICS_ENABLED');
    } else {
      process.env['OPS_ANALYTICS_ENABLED'] = originalAnalyticsEnabled;
    }
  }
});
```

## Testing Checklist

Check all that apply:

- [x] I tested the feature thoroughly, including edge cases

- [x] I verified all affected areas still work as expected

- [x] Automated tests were added/updated if necessary

- [x] Changes are backwards compatible with any existing data, otherwise
a migration script is provided

## Visual Changes (if applicable)

N/A

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: maor-rozenfeld <49363375+maor-rozenfeld@users.noreply.github.com>
…#1803)

The test for analytics being disabled only verified that analytics GET
routes were skipped, but didn't confirm that essential POST routes
(`/sign-up`, `/sign-in`, `/sign-out`) remained functional.

## Changes

Enhanced `skips analytics routes when analytics are disabled` test to
verify:
- Analytics GET routes are not registered (existing)
- All three POST authentication routes are registered with correct
paths, options, and handlers (new)

```typescript
// Now verifies both what's disabled and what remains active
expect(app.get).not.toHaveBeenCalled();
expect(app.post).toHaveBeenCalledTimes(3);

const signUpRoute = app.post.mock.calls.find(([path]) => path === '/sign-up');
expect(signUpRoute).toBeDefined();
expect(signUpRoute?.[1]).toEqual(expect.any(Object));
expect(signUpRoute?.[2]).toEqual(expect.any(Function));
// Similar checks for /sign-in and /sign-out
```

## Additional Notes

Addresses review feedback from #1802 requesting verification that core
authentication functionality remains intact when analytics is disabled.

## Testing Checklist

- [x] I tested the feature thoroughly, including edge cases
- [x] I verified all affected areas still work as expected
- [x] Automated tests were added/updated if necessary
- [x] Changes are backwards compatible with any existing data, otherwise
a migration script is provided

## Visual Changes (if applicable)

N/A - test-only changes

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in
our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: maor-rozenfeld <49363375+maor-rozenfeld@users.noreply.github.com>
@maor-rozenfeld maor-rozenfeld requested a review from Copilot January 6, 2026 12:16
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

packages/server/api/test/unit/authentication/authentication.controller.test.ts:1

  • The assertion checks index [2] for the handler function, but based on the registration pattern in line 111 where embedRoute?.[1] is checked for the /analytics-embed-id route (which has no options object), the handler should be at index [1], not [2]. This index should match the pattern used for the embed route.
import { FastifyInstance } from 'fastify';

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +232 to +234
value: system.isAnalyticsEnabled()
? system.get(AppSystemProp.ANALYTICS_PUBLIC_URL)
: undefined,
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

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

The conditional logic returns undefined when analytics is disabled, but system.get() already returns undefined when the value is not set. Consider simplifying to return system.get(AppSystemProp.ANALYTICS_PUBLIC_URL) ?? undefined when analytics is enabled, or verify if there's a scenario where the URL could be set but analytics disabled.

Copilot uses AI. Check for mistakes.
Comment on lines 22 to 24
const { data: analyticsPublicUrl } = flagsHooks.useFlag<string | undefined>(
FlagId.ANALYTICS_PUBLIC_URL,
);
Copy link
Contributor

@alexandrudanpop alexandrudanpop Jan 9, 2026

Choose a reason for hiding this comment

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

this leads to an issue if ANALYTICS_ENABLED=false but someone still leaves ANALYTICS_PUBLIC_URL in .env. Since you added ANALYTICS_ENABLED I would propose to also use it here and in the router file.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

what i mean it's not consistent as the check in the BE is different using the new var

FlagId.FEDERATED_LOGIN_ENABLED,
);

const { data: analyticsPublicUrl } = flagsHooks.useFlag<string | undefined>(
Copy link
Contributor

@cezudas cezudas Jan 9, 2026

Choose a reason for hiding this comment

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

It slightly violates rule of hooks, it still works because createRoutes() is called directly inside the component, at the top level. It is consistent with the other flag checks above.

React Hook "useHasAnalyticsAccess" is called in function "createRoutes" that is neither a React function component nor a custom React Hook function.

…alytics route and analytics menu link (#1822)

Part of OPS-3284

---------

Co-authored-by: Marcelo Gonçalves <marcelo@openops.com>
@maor-rozenfeld maor-rozenfeld requested a review from Copilot January 9, 2026 15:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 40 out of 40 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

/* eslint-disable @typescript-eslint/no-empty-function */

export const analyticsAccessService = {
verifyUserAnalyticsAccess(_: string): void {},
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

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

The parameter name '_' is not descriptive. Use a meaningful name like 'userId' or 'openopsUserId' to match the type definition in access-service-factory.ts.

Suggested change
verifyUserAnalyticsAccess(_: string): void {},
verifyUserAnalyticsAccess(userId: string): void {},

Copilot uses AI. Check for mistakes.
# Conflicts:
#	packages/react-ui/src/app/features/navigation/lib/menu-links-hook.ts
#	packages/react-ui/src/app/router.tsx
#	packages/server/api/src/app/authentication/authentication.controller.ts
@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 9, 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.

5 participants