-
Notifications
You must be signed in to change notification settings - Fork 8
CLI-549 Add sonar integrate antigravity command and install orchestration #407
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/nq/CLI-548-integrate-antigravity
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| /* | ||
| * SonarQube CLI | ||
| * Copyright (C) SonarSource Sàrl | ||
| * mailto:info AT sonarsource DOT com | ||
| * | ||
| * This program is free software; you can redistribute it and/or | ||
| * modify it under the terms of the GNU Lesser General Public | ||
| * License as published by the Free Software Foundation; either | ||
| * version 3 of the License, or (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| * Lesser General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Lesser General Public License | ||
| * along with this program; if not, write to the Free Software Foundation, | ||
| * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| */ | ||
|
|
||
| import { join } from 'node:path'; | ||
|
|
||
| import { | ||
| ANTIGRAVITY_GLOBAL_SKILLS_DIR, | ||
| ANTIGRAVITY_PROJECT_AGENTS_DIR, | ||
| } from '../../../../lib/config-constants'; | ||
| import { createContextAugmentationFeature } from '../_common/features/context-augmentation-feature'; | ||
| import type { IntegrationContext, IntegrationDeclaration } from '../_common/registry'; | ||
| import { askUser } from '../_common/registry'; | ||
| import type { IntegrateAgentOptions } from '../_common/types'; | ||
|
|
||
| export const ANTIGRAVITY_INTEGRATION_ID = 'antigravity-cli'; | ||
|
|
||
| export interface AntigravityIntegrationOptions extends IntegrateAgentOptions { | ||
| projectRoot?: string; | ||
| globalSecretsHookExists?: boolean; | ||
| /** Install PostInvocation SQAA hook (project scope). Wired in CLI-551. */ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's fine to drop this comment
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like to write comments on feature branch to make sure I don't forget about implementation of each tickets, but thanks for suggesting to target master directly! I think it makes sense, I'll remove all the temporary bits I added |
||
| installSqaaHook?: boolean; | ||
| sqaaEntitled?: boolean; | ||
| installContextAugmentation?: boolean; | ||
| } | ||
|
|
||
| /** | ||
| * Minimal declarative integration for CLI-549 orchestration. Secrets hooks, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TMI ? :D |
||
| * SQAA, and MCP features are added in CLI-550/CLI-551. | ||
| */ | ||
| export const antigravityIntegration: IntegrationDeclaration<AntigravityIntegrationOptions> = { | ||
| id: ANTIGRAVITY_INTEGRATION_ID, | ||
| displayName: 'Antigravity', | ||
| features: [ | ||
| { | ||
| id: 'integration-setup', | ||
| displayName: 'Antigravity integration setup', | ||
| shouldInstall: () => askUser(), | ||
| }, | ||
| createContextAugmentationFeature<AntigravityIntegrationOptions>({ | ||
| agentDisplayName: 'Antigravity', | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will the same integration also work with Antigravity IDE? Or only CLI? Depending on the answer we might want to update this display name or the integration ID on line 32 |
||
| targetPath: resolveAntigravitySkillPath, | ||
| }), | ||
| ], | ||
| }; | ||
|
|
||
| function resolveAntigravitySkillPath(context: IntegrationContext): string { | ||
| if (context.scope === 'global') { | ||
| return join(ANTIGRAVITY_GLOBAL_SKILLS_DIR, 'sonar-context-augmentation', 'SKILL.md'); | ||
| } | ||
| return join( | ||
| context.targetRoot, | ||
| ANTIGRAVITY_PROJECT_AGENTS_DIR, | ||
| 'skills', | ||
| 'sonar-context-augmentation', | ||
| 'SKILL.md', | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| /* | ||
| * SonarQube CLI | ||
| * Copyright (C) SonarSource Sàrl | ||
| * mailto:info AT sonarsource DOT com | ||
| * | ||
| * This program is free software; you can redistribute it and/or | ||
| * modify it under the terms of the GNU Lesser General Public | ||
| * License as published by the Free Software Foundation; either | ||
| * version 3 of the License, or (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| * Lesser General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Lesser General Public License | ||
| * along with this program; if not, write to the Free Software Foundation, | ||
| * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| */ | ||
|
|
||
| /** | ||
| * Probe for a global Antigravity secrets hook install. Returns the active hook | ||
| * script path when a healthy global install is found so project-level secrets | ||
| * hooks can be skipped to avoid double-scanning. | ||
| */ | ||
| export function detectGlobalSecretsHook(): string | undefined { | ||
| return undefined; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| /* | ||
| * SonarQube CLI | ||
| * Copyright (C) SonarSource Sàrl | ||
| * mailto:info AT sonarsource DOT com | ||
| * | ||
| * This program is free software; you can redistribute it and/or | ||
| * modify it under the terms of the GNU Lesser General Public | ||
| * License as published by the Free Software Foundation; either | ||
| * version 3 of the License, or (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| * Lesser General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Lesser General Public License | ||
| * along with this program; if not, write to the Free Software Foundation, | ||
| * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| */ | ||
|
|
||
| import type { ResolvedAuth } from '../../../../lib/auth-resolver'; | ||
| import type { IntegrationStateAttribute } from '../../../../lib/state'; | ||
| import { info } from '../../../../ui'; | ||
| import { displayAgentIntegratePrelude } from '../_common/agent-integrate-prelude'; | ||
| import { | ||
| buildContextAugmentationAttrs, | ||
| resolveContextAugmentationSetup, | ||
| } from '../_common/context-augmentation'; | ||
| import { installIntegration } from '../_common/registry'; | ||
| import { resolveSqaaSetup } from '../_common/sqaa-entitlement'; | ||
| import type { IntegrateAgentOptions } from '../_common/types'; | ||
| import { supportedIntegrations } from '../index.js'; | ||
| import { ANTIGRAVITY_INTEGRATION_ID, type AntigravityIntegrationOptions } from './declaration'; | ||
| import { detectGlobalSecretsHook } from './hooks'; | ||
| import { resolveAntigravityInstallTarget } from './install-target'; | ||
|
|
||
| export async function integrateAntigravity( | ||
| options: IntegrateAgentOptions, | ||
| auth: ResolvedAuth, | ||
| ): Promise<void> { | ||
| const ctx = await displayAgentIntegratePrelude('Antigravity', 'antigravity', options, auth); | ||
|
|
||
| if (options.skipContext) { | ||
| info('Skipping Context Augmentation (--skip-context).'); | ||
| } | ||
| const contextAugmentation = options.skipContext | ||
| ? null | ||
| : await resolveContextAugmentationSetup({ | ||
| auth, | ||
| projectKey: ctx.projectKey, | ||
| isGlobal: ctx.isGlobal, | ||
| }); | ||
|
|
||
| const sqaaEntitled = await resolveSqaaSetup({ | ||
| serverURL: ctx.serverUrl, | ||
| token: ctx.token, | ||
| organization: ctx.organization, | ||
| isGlobal: ctx.isGlobal, | ||
| }); | ||
| const installSqaaHook = sqaaEntitled && ctx.projectKey !== undefined; | ||
|
|
||
| const { installRoot: targetRoot, installScope: scope } = resolveAntigravityInstallTarget( | ||
| ctx.isGlobal, | ||
| ctx.project.rootDir, | ||
| ); | ||
| const existingGlobalHookPath = ctx.isGlobal ? undefined : detectGlobalSecretsHook(); | ||
| const globalSecretsHookExists = existingGlobalHookPath !== undefined; | ||
|
|
||
| const integrationOptions: AntigravityIntegrationOptions = { | ||
| ...options, | ||
| projectRoot: ctx.project.rootDir, | ||
| globalSecretsHookExists, | ||
| installSqaaHook, | ||
| sqaaEntitled, | ||
| installContextAugmentation: contextAugmentation !== null, | ||
| }; | ||
|
|
||
| await installIntegration({ | ||
| registry: supportedIntegrations, | ||
| integrationId: ANTIGRAVITY_INTEGRATION_ID, | ||
| options: integrationOptions, | ||
| targetRoot, | ||
| scope, | ||
| auth, | ||
| nonInteractive: options.nonInteractive, | ||
| attrs: { | ||
| ...buildIntegrationAttrs(ctx), | ||
| ...(contextAugmentation | ||
| ? buildContextAugmentationAttrs( | ||
| ctx.serverUrl, | ||
| ctx.organization, | ||
| contextAugmentation.scaEnabled, | ||
| ) | ||
| : {}), | ||
| }, | ||
| }); | ||
| } | ||
|
|
||
| function buildIntegrationAttrs(ctx: { | ||
| serverUrl: string; | ||
| organization: string | undefined; | ||
| projectKey: string | undefined; | ||
| }): Record<string, IntegrationStateAttribute> { | ||
| return { | ||
| projectKey: ctx.projectKey ?? null, | ||
| serverUrl: ctx.serverUrl, | ||
| orgKey: ctx.organization ?? null, | ||
| }; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /* | ||
| * SonarQube CLI | ||
| * Copyright (C) SonarSource Sàrl | ||
| * mailto:info AT sonarsource DOT com | ||
| * | ||
| * This program is free software; you can redistribute it and/or | ||
| * modify it under the terms of the GNU Lesser General Public | ||
| * License as published by the Free Software Foundation; either | ||
| * version 3 of the License, or (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| * Lesser General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Lesser General Public License | ||
| * along with this program; if not, write to the Free Software Foundation, | ||
| * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| */ | ||
|
|
||
| import { ANTIGRAVITY_GLOBAL_CONFIG_DIR } from '../../../../lib/config-constants'; | ||
| import type { IntegrationScope } from '../../../../lib/state'; | ||
|
|
||
| export function resolveAntigravityInstallTarget( | ||
| isGlobal: boolean, | ||
| projectRoot: string, | ||
| ): { installRoot: string; installScope: IntegrationScope } { | ||
| return { | ||
| installRoot: isGlobal ? ANTIGRAVITY_GLOBAL_CONFIG_DIR : projectRoot, | ||
| installScope: isGlobal ? 'global' : 'project', | ||
| }; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |
| */ | ||
|
|
||
| import { createIntegrationRegistry } from './_common/registry'; | ||
| import { antigravityIntegration } from './antigravity/declaration'; | ||
| import { claudeIntegration } from './claude/declaration'; | ||
| import { codexIntegration } from './codex/declaration'; | ||
| import { copilotIntegration } from './copilot/declaration'; | ||
|
|
@@ -28,6 +29,7 @@ export const ALL_INTEGRATIONS = [ | |
| claudeIntegration, | ||
| copilotIntegration, | ||
| codexIntegration, | ||
| antigravityIntegration, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think at some point we said we should not have feature branches. So instead I would suggest removing this change / making |
||
| ...GIT_INTEGRATIONS, | ||
| ] as const; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -69,6 +69,42 @@ export const BIN_DIR = join(CLI_DIR, 'bin'); | |
| /** Directory used for global git hooks when core.hooksPath is set via sonar integrate git --global. */ | ||
| export const GLOBAL_HOOKS_DIR = join(CLI_DIR, 'hooks'); | ||
|
|
||
| // --------------------------------------------------------------------------- | ||
| // Antigravity | ||
| // --------------------------------------------------------------------------- | ||
|
|
||
| /** Antigravity workspace agents directory (relative to the project root). */ | ||
| export const ANTIGRAVITY_PROJECT_AGENTS_DIR = '.agents'; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might be wrong but I vaguely remember Codex also having a similar path? Just something to double-check, not to have duplicate or overwritten integrations |
||
|
|
||
| /** Project Antigravity hooks config (relative to the project root). */ | ||
| export const ANTIGRAVITY_PROJECT_HOOKS_JSON = join(ANTIGRAVITY_PROJECT_AGENTS_DIR, 'hooks.json'); | ||
|
|
||
| /** Project Sonar hook scripts directory (relative to the project root). */ | ||
| export const ANTIGRAVITY_PROJECT_SONAR_HOOKS_DIR = join( | ||
| ANTIGRAVITY_PROJECT_AGENTS_DIR, | ||
| 'sonar', | ||
| 'hooks', | ||
| ); | ||
|
|
||
| /** | ||
| * Global Antigravity config root (`sonar integrate antigravity --global`). | ||
| * Hook scripts and config patches live under this tree (not a plugin bundle). | ||
| */ | ||
| export const ANTIGRAVITY_GLOBAL_CONFIG_DIR = join(homedir(), '.gemini', 'config'); | ||
|
|
||
| /** Global Antigravity hooks config (`sonar integrate antigravity --global`). */ | ||
| export const ANTIGRAVITY_GLOBAL_HOOKS_JSON = join(ANTIGRAVITY_GLOBAL_CONFIG_DIR, 'hooks.json'); | ||
|
|
||
| /** Global Sonar hook scripts directory (`sonar integrate antigravity --global`). */ | ||
| export const ANTIGRAVITY_GLOBAL_SONAR_HOOKS_DIR = join( | ||
| ANTIGRAVITY_GLOBAL_CONFIG_DIR, | ||
| 'sonar', | ||
| 'hooks', | ||
| ); | ||
|
|
||
| /** Global Antigravity skills directory (`sonar integrate antigravity --global` CAG skill). */ | ||
| export const ANTIGRAVITY_GLOBAL_SKILLS_DIR = join(ANTIGRAVITY_GLOBAL_CONFIG_DIR, 'skills'); | ||
|
|
||
| // --------------------------------------------------------------------------- | ||
| // Sonarsource binaries | ||
| // --------------------------------------------------------------------------- | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above. Maybe it's best to keep the groundwork but remove wiring from customer-facing surfaces.