diff --git a/.github/renovate.json5 b/.github/renovate.json5 index f3eb783..f69f79b 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -20,6 +20,10 @@ ], pinDigests: true, }, + { + matchPackageNames: ['googleapis/genai-toolbox'], + 'semanticCommitType': 'feat' + } ], customManagers: [ { diff --git a/.github/workflows/assign-issues.yml b/.github/workflows/assign-issues.yml new file mode 100644 index 0000000..1dffe25 --- /dev/null +++ b/.github/workflows/assign-issues.yml @@ -0,0 +1,32 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Issue assignment + +on: + issues: + types: [opened] + +jobs: + auto-assign: + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - name: "Auto-assign issue" + uses: pozil/auto-assign-issue@v2 + with: + assignees: ajupazhamayil,dolphin1999,rachelhmyang,Myst9 + numOfAssignee: 1 + abortIfPreviousAssignees: true diff --git a/.github/workflows/assign-prs.yml b/.github/workflows/assign-prs.yml new file mode 100644 index 0000000..972278a --- /dev/null +++ b/.github/workflows/assign-prs.yml @@ -0,0 +1,32 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: PR assignment + +on: + pull_request: + types: [opened, edited, synchronize, reopened] + +jobs: + auto-assign: + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: "Auto-assign PR" + uses: pozil/auto-assign-issue@v2 + with: + assignees: ajupazhamayil,dolphin1999,rachelhmyang,Myst9 + numOfAssignee: 1 + abortIfPreviousAssignees: true diff --git a/.github/workflows/header-check.yml b/.github/workflows/header-check.yml index 81868b2..3c8ef48 100644 --- a/.github/workflows/header-check.yml +++ b/.github/workflows/header-check.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@v5 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - name: Check License Header - uses: apache/skywalking-eyes/header@v0.7.0 + uses: apache/skywalking-eyes/header@5c5b974209f0de5d905f37deb69369068ebfc15c # v0.7.0 diff --git a/.github/workflows/mirror-changelog.yml b/.github/workflows/mirror-changelog.yml new file mode 100644 index 0000000..c584350 --- /dev/null +++ b/.github/workflows/mirror-changelog.yml @@ -0,0 +1,134 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Mirror Toolbox Changelog + +on: + pull_request_target: + types: [opened, edited] + +jobs: + add-release-notes: + if: github.actor == 'renovate[bot]' && startsWith(github.head_ref, 'renovate/googleapis-genai-toolbox') + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + - name: Add Toolbox Release Notes to PR Body + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + REQUIRED_KEYWORDS: 'mssql' + with: + script: | + const requiredKeywordsEnv = process.env.REQUIRED_KEYWORDS; + const requiredKeywords = requiredKeywordsEnv.split(',').map(kw => kw.trim()).filter(kw => kw.length > 0); + + const prBody = context.payload.pull_request.body || ''; + + // Extract the relevant changelog section + const startMarker = 'googleapis/genai-toolbox'; + const endMarker = ''; + const startIndex = prBody.indexOf(startMarker); + const endIndex = prBody.indexOf(endMarker, startIndex); + + if (startIndex === -1 || endIndex === -1) { + console.log('Could not find the release notes section in the PR body. Exiting.'); + return; + } + const releaseNotesSection = prBody.substring(startIndex, endIndex); + + // Parse, Filter, and transform + const prefixesToFilter = ['source/', 'sources/', 'tool/', 'tools/']; + + // Use a map for cleaner type switching + const typeMap = { + '##### ⚠ BREAKING CHANGES': 'feat!', + '##### Features': 'feat', + '##### Bug Fixes': 'fix', + '##### Chores': 'ignore', + '##### Miscellaneous Chores': 'ignore', + '##### Documentation': 'ignore', + }; + + let currentType = 'feat'; // Default + const newChangelog = []; + + for (const line of releaseNotesSection.split('\n')) { + const trimmedLine = line.trim(); + + // Update current type if it's a header + if (typeMap[trimmedLine]) { + currentType = typeMap[trimmedLine]; + continue; + } + + // Skip ignored sections + if (currentType === 'ignore') { + continue; + } + + // Match and extract changelog item + const itemMatch = trimmedLine.match(/^[*-]\s(.*)$/); + if (itemMatch) { + const originalContent = itemMatch[1]; + const lineAsLowerCase = originalContent.toLowerCase(); + + const hasPrefix = prefixesToFilter.some(prefix => lineAsLowerCase.includes(prefix)); + + // Check if the line includes ANY of the required keywords + let hasAnyRequiredKeyword = false; + if (requiredKeywords.length > 0) { + hasAnyRequiredKeyword = requiredKeywords.some(keyword => lineAsLowerCase.includes(keyword)); + } + + // Include if it doesn't have a prefix OR it has any of the required keywords + if (!hasPrefix || hasAnyRequiredKeyword) { + newChangelog.push(`- ${currentType}: ${originalContent}`); + } else { + console.log(`Filtering out: ${originalContent}`); + } + } + } + + if (newChangelog.length === 0) { + console.log('Found no changelog items to add after filtering. Exiting.'); + return; + } + + // Construct the override block + const overrideBlock = [ + '\n\nBEGIN_COMMIT_OVERRIDE', + ...newChangelog, + 'END_COMMIT_OVERRIDE' + ].join('\n'); + + // Update PR body + const baseBody = prBody.split('\n\nBEGIN_COMMIT_OVERRIDE')[0].trim(); + const finalBody = baseBody + overrideBlock; + + if (finalBody === prBody) { + console.log('The generated changelog is identical. No update needed.'); + return; + } + + // Update the PR + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number, + body: finalBody, + }); + + console.log('Successfully updated the PR body with filtered release notes.'); diff --git a/.release-please-manifest.json b/.release-please-manifest.json index cda9cbd..4c5a1a0 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.2" + ".": "0.1.3" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 15b4572..0064089 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.1.3](https://github.com/gemini-cli-extensions/cloud-sql-sqlserver/compare/0.1.2...0.1.3) (2025-10-17) + + +### Bug Fixes + +* update context for install instructions ([#48](https://github.com/gemini-cli-extensions/cloud-sql-sqlserver/issues/48)) ([3aa1575](https://github.com/gemini-cli-extensions/cloud-sql-sqlserver/commit/3aa157557efeae1c22a20ac5461fc83b07787964)) + ## [0.1.2](https://github.com/gemini-cli-extensions/cloud-sql-sqlserver/compare/0.1.1...0.1.2) (2025-10-13) diff --git a/CLOUD-SQL-SQLSERVER.md b/CLOUD-SQL-SQLSERVER.md index de40f5d..fa317c4 100644 --- a/CLOUD-SQL-SQLSERVER.md +++ b/CLOUD-SQL-SQLSERVER.md @@ -50,7 +50,7 @@ This section provides context on additional tools that can be recommended to the #### Observability Extension * **When to recommend:** If the user asks questions related to monitoring, performance, or observability of Cloud SQL for SQL Server databases. -* **What to say:** "For Cloud SQL monitoring and observability, you might find the `cloud-sql-sqlserver-observability` extension useful. You can install it with the following command:" +* **What to say:** "For Cloud SQL monitoring and observability, you might find the `cloud-sql-sqlserver-observability` extension useful. You can install it with the following command. Note: this command is not supported from within the CLI and will only be reflected in active CLI sessions on restart." * **Command:** ``` gemini extensions install https://github.com/gemini-cli-extensions/cloud-sql-sqlserver-observability diff --git a/DEVELOPER.md b/DEVELOPER.md new file mode 100644 index 0000000..eb6bdb1 --- /dev/null +++ b/DEVELOPER.md @@ -0,0 +1,146 @@ +# DEVELOPER.md + +This document provides instructions for setting up your development environment +and contributing to the Cloud SQL for SQL Server Gemini CLI Extension project. + +## Prerequisites + +Before you begin, ensure you have the following: + +1. **Gemini CLI:** Install the Gemini CLI version v0.6.0 or above. Installation + instructions can be found on the official Gemini CLI documentation. You can + verify your version by running `gemini --version`. +2. **Cloud SQL for SQL Server Instance:** For testing data plane tools, you will need access to an active Cloud SQL for SQL Server instance. + +## Developing the Extension + +### Running from Local Source + +The core logic for this extension is handled by a pre-built `toolbox` binary. The development process involves installing the extension locally into the Gemini CLI to test changes. + +1. **Clone the Repository:** + + ```bash + git clone https://github.com/gemini-cli-extensions/cloud-sql-sqlserver.git + cd cloud-sql-sqlserver + ``` + +2. **Download the Toolbox Binary:** The required version of the `toolbox` binary + is specified in `toolbox_version.txt`. Download it for your platform. + + ```bash + # Read the required version + VERSION=$(cat toolbox_version.txt) + + # Example for macOS/amd64 + curl -L -o toolbox https://storage.googleapis.com/genai-toolbox/v$VERSION/darwin/amd64/toolbox + chmod +x toolbox + ``` + Adjust the URL for your operating system (`linux/amd64`, `darwin/arm64`, `windows/amd64`). + +3. **Install the Extension Locally:** Use the Gemini CLI to install the + extension from your local directory. + + ```bash + gemini extensions install . + gemini extensions link . + ``` + The CLI will prompt you to confirm the installation. Accept it to proceed. + +4. **Testing Changes:** After installation, start the Gemini CLI (`gemini`). + You can now interact with the `cloud-sql-sqlserver` tools to manually test your changes + against your connected database. + +## Testing + +### Automated Presubmit Checks + +A GitHub Actions workflow (`.github/workflows/presubmit-tests.yml`) is triggered +for every pull request. This workflow primarily verifies that the extension can +be successfully installed by the Gemini CLI. + +Currently, there are no automated unit or integration test suites +within this repository. All functional testing must be performed manually. All tools +are currently tested in the [MCP Toolbox GitHub](https://github.com/googleapis/genai-toolbox). + +### Other GitHub Checks + +* **License Header Check:** A workflow ensures all necessary files contain the + proper license header. +* **Conventional Commits:** This repository uses + [Release Please](https://github.com/googleapis/release-please) to manage + releases. Your commit messages must adhere to the + [Conventional Commits](https://www.conventionalcommits.org/) specification. +* **Dependency Updates:** [Renovate](https://github.com/apps/forking-renovate) + is configured to automatically create pull requests for dependency updates. + +## Building the Extension + +The "build" process for this extension involves packaging the extension's +metadata files (`gemini-extension.json`, `cloud-sql-sqlserver.md`, `LICENSE`) along with the +pre-built `toolbox` binary into platform-specific archives (`.tar.gz` or `.zip`). + +This process is handled automatically by the +[`package-and-upload-assets.yml`](.github/workflows/package-and-upload-assets.yml) +GitHub Actions workflow when a new release is created. Manual building is not +required. + +## Maintainer Information + +### Team + +The primary maintainers for this repository are defined in the +[`.github/CODEOWNERS`](.github/CODEOWNERS) file: + +* `@gemini-cli-extensions/senseai-eco` +* `@gemini-cli-extensions/cloud-sql-sqlserver-maintainers` + +### Releasing + +The release process is automated using `release-please`. It consists of an automated changelog preparation step followed by the manual merging of a Release PR. + +#### Automated Changelog Enrichment + +Before a Release PR is even created, a special workflow automatically mirrors +relevant changelogs from the core `googleapis/genai-toolbox` dependency. This +ensures that the release notes for this extension accurately reflect important +upstream changes. + +The process is handled by the [`mirror-changelog.yml`](.github/workflows/mirror-changelog.yml) workflow: + +1. **Trigger:** The workflow runs automatically on pull requests created by + Renovate for `toolbox` version updates. +2. **Parsing:** It reads the detailed release notes that Renovate includes in + the PR body. +3. **Filtering:** These release notes are filtered to include only changes + relevant to this extension. The relevance is determined by a keyword (e.g., + `mssql`), passed as an environment variable in the workflow file. +4. **Changelog Injection:** The script formats the filtered entries as + conventional commits and injects them into the PR body within a + `BEGIN_COMMIT_OVERRIDE` block. +5. **Release Please:** When the main Release PR is created, `release-please` + reads this override block instead of the standard `chore(deps): ...` commit + message, effectively mirroring the filtered upstream changelog into this + project's release notes. + +> **Note for Maintainers:** The filtering script is an automation aid, but it +> may occasionally produce "false positives" (e.g., an internal logging change +> that happens to contain the keyword). Before merging a `toolbox` dependency +> PR, maintainers must **review the generated `BEGIN_COMMIT_OVERRIDE` block** +> and manually delete any lines that are not relevant to the end-users of this +> extension. The curated override block is the final source of truth for the +> release changelog. + +#### Release Process + +1. **Release PR:** When commits with conventional commit headers (e.g., `feat:`, + `fix:`) are merged into the `main` branch, `release-please` will + automatically create or update a "Release PR". +2. **Merge Release PR:** A maintainer approves and merges the Release PR. This + action triggers `release-please` to create a new GitHub tag and a + corresponding GitHub Release. +3. **Package and Upload:** The new release triggers the + `package-and-upload-assets.yml` workflow. This workflow builds the + platform-specific extension archives and uploads them as assets to the + GitHub Release. + diff --git a/README.md b/README.md index 777b68d..4f3e17e 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,21 @@ Learn more about [Gemini CLI Extensions](https://github.com/google-gemini/gemini * **Natural Language Management:** Stop wrestling with complex commands. Explore schemas and query data by describing what you want in plain English. * **Code Generation:** Accelerate development by asking Gemini to generate data classes and other code snippets based on your table schemas. +> [!IMPORTANT] +> **We Want Your Feedback!** +> Please share your thoughts with us by filling out our feedback [form][form]. +> Your input is invaluable and helps us improve the project for everyone. + +[form]: https://docs.google.com/forms/d/e/1FAIpQLSfEGmLR46iipyNTgwTmIDJqzkAwDPXxbocpXpUbHXydiN1RTw/viewform?usp=pp_url&entry.157487=cloud-sql-sqlserver + ## Prerequisites Before you begin, ensure you have the following: * [Gemini CLI](https://github.com/google-gemini/gemini-cli) installed with version **+v0.6.0**. +* Setup Gemini CLI [Authentication](https://github.com/google-gemini/gemini-cli/tree/main?tab=readme-ov-file#-authentication-options). * A Google Cloud project with the **Cloud SQL Admin API** enabled. +* Ensure [Application Default Credentials](https://cloud.google.com/docs/authentication/gcloud) are available in your environment. * IAM Permissions: * Cloud SQL Client (`roles/cloudsql.client`) * Cloud SQL Viewer (`roles/cloudsql.viewer`) @@ -36,17 +45,19 @@ gemini extensions install https://github.com/gemini-cli-extensions/cloud-sql-sql ### Configuration -Set the following environment variables before starting the Gemini CLI. +Set the following environment variables before starting the Gemini CLI. These variables can be loaded from a `.env` file. This configuration is not required if utilizing the [Admin toolset](#supported-tools). -* `CLOUD_SQL_MSSQL_PROJECT`: The GCP project ID. -* `CLOUD_SQL_MSSQL_REGION`: The region of your Cloud SQL instance. -* `CLOUD_SQL_MSSQL_INSTANCE`: The ID of your Cloud SQL instance. -* `CLOUD_SQL_MSSQL_DATABASE`: The name of the database to connect to. -* `CLOUD_SQL_MSSQL_IP_ADDRESS`: The IP address of the Cloud SQL instance. -* `CLOUD_SQL_MSSQL_USER`: The database username. -* `CLOUD_SQL_MSSQL_PASSWORD`: The password for the database user. -* `CLOUD_SQL_MSSQL_IP_TYPE`: (Optional) The IP type i.e. “Public” or “Private” (Default: Public). +```bash +export CLOUD_SQL_MSSQL_PROJECT="" +export CLOUD_SQL_MSSQL_REGION="" +export CLOUD_SQL_MSSQL_INSTANCE="" +export CLOUD_SQL_MSSQL_DATABASE="" +export CLOUD_SQL_MSSQL_IP_ADDRESS="" +export CLOUD_SQL_MSSQL_USER="" +export CLOUD_SQL_MSSQL_PASSWORD="" +export CLOUD_SQL_MSSQL_IP_TYPE="PUBLIC" # Optional: `PUBLIC`, `PRIVATE`. Defaults to `PUBLIC`. +``` Ensure [Application Default Credentials](https://cloud.google.com/docs/authentication/gcloud) are available in your environment. @@ -66,45 +77,6 @@ gemini > Currently, the database connection must be configured before starting the Gemini CLI and can not be changed during a session. > To save and resume conversation history use command: `/chat save ` and `/chat resume `. -### Start Gemini CLI - -To start the Gemini CLI, use the following command: - -```bash -gemini -``` - -> [!WARNING] -> **Changing Instance & Database Connections** -> Currently, the database connection must be configured before starting the Gemini CLI and can not be changed during a session. -> To save and resume conversation history use command: `/chat save ` and `/chat resume `. - -### Start Gemini CLI - -To start the Gemini CLI, use the following command: - -```bash -gemini -``` - -> [!WARNING] -> **Changing Instance & Database Connections** -> Currently, the database connection must be configured before starting the Gemini CLI and can not be changed during a session. -> To save and resume conversation history use command: `/chat save ` and `/chat resume `. - -### Start Gemini CLI - -To start the Gemini CLI, use the following command: - -```bash -gemini -``` - -> [!WARNING] -> **Changing Instance & Database Connections** -> Currently, the database connection must be configured before starting the Gemini CLI and can not be changed during a session. -> To save and resume conversation history use command: `/chat save ` and `/chat resume `. - ## Usage Examples Interact with Cloud SQL for SQL Server using natural language: @@ -121,7 +93,7 @@ Interact with Cloud SQL for SQL Server using natural language: ## Supported Tools -* **Admin:** +* **Admin:** * `create_instance`: Use this tool to create an SQL Server instance. * `create_user`: Use this tool to create SQL Server-BUILT-IN or IAM-based users. * `get_instance`: Use this tool to get details about an SQL Server instance. @@ -130,7 +102,7 @@ Interact with Cloud SQL for SQL Server using natural language: * `list_users`: Use this tool to list users in a given project and location. * `wait_for_operation`: Use this tool to poll the operations API until the operation is done. -* **Data:** +* **Data:** * `list_tables`: Use this tool to list tables and descriptions. * `execute_sql`: Use this tool to execute any SQL statement. @@ -143,6 +115,11 @@ Find additional extensions to support your entire software development lifecycle ## Troubleshooting +Use `gemini --debug` to enable debugging. + +Common issues: + +* "failed to find default credentials: google: could not find default credentials.": Ensure [Application Default Credentials](https://cloud.google.com/docs/authentication/gcloud) are available in your environment. See [Set up Application Default Credentials](https://cloud.google.com/docs/authentication/external/set-up-adc) for more information. * "✖ Error during discovery for server: MCP error -32000: Connection closed": The database connection has not been established. Ensure your configuration is set via environment variables. -* "✖ MCP ERROR: Error: spawn /Users//.gemini/extensions/cloud-sql-sqlserver/toolbox ENOENT": The Toolbox binary did not download correctly. Ensure you are using Gemini CLI v0.6.0+. +* "✖ MCP ERROR: Error: spawn /Users/USER/.gemini/extensions/cloud-sql-sqlserver/toolbox ENOENT": The Toolbox binary did not download correctly. Ensure you are using Gemini CLI v0.6.0+. * "cannot execute binary file": The Toolbox binary did not download correctly. Ensure the correct binary for your OS/Architecture has been downloaded. See [Installing the server](https://googleapis.github.io/genai-toolbox/getting-started/introduction/#installing-the-server) for more information. diff --git a/gemini-extension.json b/gemini-extension.json index cd8d541..09b3bc4 100644 --- a/gemini-extension.json +++ b/gemini-extension.json @@ -1,6 +1,6 @@ { "name": "cloud-sql-sqlserver", - "version": "0.1.2", + "version": "0.1.3", "description": "Connect to Cloud SQL for SQL Server", "mcpServers": { "cloud_sql_sqlserver_admin": {