diff --git a/.github/config/nodejs-dev.jsonc b/.github/config/nodejs-dev.jsonc index d5023eb78b..627ae0a1da 100644 --- a/.github/config/nodejs-dev.jsonc +++ b/.github/config/nodejs-dev.jsonc @@ -100,6 +100,7 @@ "auth", "batch", "cloud-language", + "cloud-sql/mysql/mysql", "cloud-tasks/snippets", "cloud-tasks/tutorial-gcf/app", "cloud-tasks/tutorial-gcf/function", diff --git a/.github/config/nodejs-prod.jsonc b/.github/config/nodejs-prod.jsonc index 36697a34d7..8d66993653 100644 --- a/.github/config/nodejs-prod.jsonc +++ b/.github/config/nodejs-prod.jsonc @@ -77,7 +77,6 @@ // TODO: fix these "ai-platform/snippets", // PERMISSION_DENIED: Permission denied: Consumer 'projects/undefined' has been suspended. "automl", // (untested) FAILED_PRECONDITION: Google Cloud AutoML Natural Language was retired on March 15, 2024. Please migrate to Vertex AI instead - "cloud-sql/mysql/mysql", // (untested) Error: expected 200 "OK", got 500 "Internal Server Error" "cloud-sql/mysql/mysql2", // (untested) Error: Cannot find module './connect-connector-with-iam-authn.js' "cloud-sql/postgres/knex", // (untested) CloudSQLConnectorError: Malformed instance connection name provided: expected format of "PROJECT:REGION:INSTANCE", got undefined "cloud-sql/sqlserver/mssql", // (untested) TypeError: The "config.server" property is required and must be of type string. diff --git a/.github/workflows/utils/sql-proxy.sh b/.github/workflows/utils/sql-proxy.sh new file mode 100755 index 0000000000..b27b7d24f8 --- /dev/null +++ b/.github/workflows/utils/sql-proxy.sh @@ -0,0 +1,95 @@ +#!/bin/bash -ex + +# 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. + +# Shared Cloud SQL Proxy setup +# Presumes the following variables in ci-setup.json: +# * CLOUD_SQL_CONNECTION_NAME - the project:region:instance of a Cloud SQL instance. +# * UNIX_SOCKET_DIR - a local directory to set the proxy to (default tmp/cloudsql) +# +# Note: in GitHub Actions environments, `/cloudsql` is not valid. +# Ensure any INSTANCE_UNIX_SOCKET value is ~= $UNIX_SOCKET_DIR/$CLOUD_SQL_CONNECTION_NAME + +usage() { + cat << EOF +# Usage: +# CLOUD_SQL_CONNECTION_NAME=project:region:instance sql-proxy.sh [..] +# +# Defaults to TCP socket proxy. Set `SOCKET=unix` for Unix sockets. +# +# Usage in package.json: +# +# "proxy": "$GITHUB_WORKSPACE/.github/workflows/utils/sql-proxy.sh", +# "system-test": "npm run proxy -- c8 mocha test/... ", +# "system-test-unix": "SOCKET=unix npm run proxy -- c8 mocha test/... ", +EOF +} + + +PROXY_VERSION="v2.15.1" +SOCKET=${SOCKET:-tcp} + +echop(){ # Print Echo + echo "👾 $1" +} + +exit_message() { # Error Echo + echo "❌ $1" + usage + exit 1 +} + +if [[ -z "$CLOUD_SQL_CONNECTION_NAME" ]]; then + exit_message "Must provide CLOUD_SQL_CONNECTION_NAME" +fi + +if [[ $SOCKET == "unix" ]]; then + UNIX_SOCKET_DIR=${UNIX_SOCKET_DIR:-"tmp/cloudsql"} + + if [[ $UNIX_SOCKET_DIR == "/cloudsql" ]]; then + exit_message "Cannot use /cloudsql in a GitHub Actions context" + fi + + mkdir -p $UNIX_SOCKET_DIR && chmod 777 $UNIX_SOCKET_DIR + socket="--unix-socket $UNIX_SOCKET_DIR" +fi +echop "Setting up cloud-sql-proxy for $SOCKET socket connections" + +# Download the Cloud SQL Auth Proxy (only once) +if [[ ! -f cloud-sql-proxy ]]; then + curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/${PROXY_VERSION}/cloud-sql-proxy.linux.amd64 + if [[ $? -ne 0 ]]; then + echo "Failed to download cloud-sql-proxy" + exit 1 + fi + chmod +x cloud-sql-proxy +else + echo "cloud-sql-proxy already downloaded" +fi + +# Setup proxy +./cloud-sql-proxy $socket $CLOUD_SQL_CONNECTION_NAME & +sleep 5 +echop "Proxy ready for use" + +# Run whatever command was passed to this script +$@ || STATUS=$? + +# Cleanup +echop "Shutting down proxy process" +pkill -f "cloud-sql-proxy" || echo "cloud-sql-proxy process not found. Was it already stopped?" + +# Fail if the tests failed +exit $STATUS diff --git a/cloud-sql/mysql/mysql/ci-setup.json b/cloud-sql/mysql/mysql/ci-setup.json new file mode 100644 index 0000000000..4b1ee8cd4c --- /dev/null +++ b/cloud-sql/mysql/mysql/ci-setup.json @@ -0,0 +1,14 @@ +{ + "env": { + "INSTANCE_HOST": "127.0.0.1", + "INSTANCE_CONNECTION_NAME": "nodejs-docs-samples-tests:us-central1:mysql-ci", + "UNIX_SOCKET_DIR": "tmp/cloudsql", + "CLOUD_SQL_CONNECTION_NAME": "$INSTANCE_CONNECTION_NAME", + "INSTANCE_UNIX_SOCKET": "$UNIX_SOCKET_DIR/$INSTANCE_CONNECTION_NAME", + "DB_NAME": "kokoro_ci", + "DB_USER": "kokoro_ci" + }, + "secrets": { + "DB_PASS": "nodejs-docs-samples-tests/nodejs-docs-samples-sql-password" + } +} diff --git a/cloud-sql/mysql/mysql/package.json b/cloud-sql/mysql/mysql/package.json index a9ee12aa61..807370d86b 100644 --- a/cloud-sql/mysql/mysql/package.json +++ b/cloud-sql/mysql/mysql/package.json @@ -13,8 +13,9 @@ }, "scripts": { "start": "node server/server.js", - "system-test": "c8 mocha -p -j 2 test/server.test.js --timeout=60000 --exit", - "system-test-unix": "c8 mocha -p -j 2 test/server-unix.test.js --timeout=60000 --exit", + "proxy": "$GITHUB_WORKSPACE/.github/workflows/utils/sql-proxy.sh", + "system-test": "npm run proxy -- c8 mocha -p -j 2 test/server.test.js --colors --timeout=60000 --exit", + "system-test-unix": "SOCKET=unix npm run proxy -- c8 mocha -p -j 2 test/server-unix.test.js --colors --timeout=60000 --exit", "test": "npm run system-test && npm run system-test-unix" }, "dependencies": {