Skip to content

Commit 8788ba2

Browse files
authored
chore: Add build.sh script with common developer commands. (#2478)
This creates a standardized developer commands script "build.sh" that will exist in this and all other Cloud SQL Connector projects. See GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#2122
1 parent a10c018 commit 8788ba2

File tree

7 files changed

+308
-51
lines changed

7 files changed

+308
-51
lines changed

.github/workflows/lint.yaml

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,7 @@ jobs:
2929
with:
3030
go-version: "1.24"
3131
- name: Checkout code
32-
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
33-
- name: >
34-
Verify go mod tidy. If you're reading this and the check has
35-
failed, run `goimports -w . && go mod tidy && golangci-lint run`
32+
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.2.2
33+
- name: lint
3634
run: |
37-
go mod tidy && git diff --exit-code
38-
- name: golangci-lint
39-
uses: golangci/golangci-lint-action@55c2c1448f86e01eaae002a5a3a9624417608d84 # v6.5.2
40-
with:
41-
version: latest
42-
args: --timeout 3m
35+
./build.sh lint_ci

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
# IDEs
55
.idea/
66
.vscode/
7+
*.iml
78

89
/cloud-sql-proxy
910
/cloud-sql-proxy.exe
1011

1112
/key.json
1213
/logs/
1314
.tools
15+
test_results.txt

.golangci.yml

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,47 +12,56 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414
# .golangci.yml
15+
version: "2"
1516
linters:
16-
disable-all: true
17+
default: none
1718
enable:
18-
# From https://golangci-lint.run/usage/linters/
19-
# This is a minor deviation from the default linters
20-
- goimports
21-
- gosimple
2219
- govet
2320
- ineffassign
2421
- revive
2522
- staticcheck
2623
- unused
27-
issues:
28-
exclude-use-default: false
29-
linters-settings:
30-
revive:
31-
rules:
32-
# From https://revive.run/docs#recommended-configuration
33-
- name: blank-imports
34-
- name: context-as-argument
35-
- name: context-keys-type
36-
- name: dot-imports
37-
- name: empty-block
38-
- name: errorf
39-
- name: error-naming
40-
- name: error-return
41-
- name: error-strings
42-
- name: exported
43-
- name: if-return
44-
- name: import-shadowing
45-
- name: increment-decrement
46-
- name: indent-error-flow
47-
- name: range
48-
- name: range-val-address
49-
- name: range-val-in-closure
50-
- name: receiver-naming
51-
- name: redefines-builtin-id
52-
- name: superfluous-else
53-
- name: time-naming
54-
- name: unexported-return
55-
- name: unreachable-code
56-
- name: unused-parameter
57-
- name: var-declaration
58-
- name: var-naming
24+
settings:
25+
revive:
26+
rules:
27+
- name: blank-imports
28+
- name: context-as-argument
29+
- name: context-keys-type
30+
- name: dot-imports
31+
- name: empty-block
32+
- name: errorf
33+
- name: error-naming
34+
- name: error-return
35+
- name: error-strings
36+
- name: exported
37+
- name: if-return
38+
- name: import-shadowing
39+
- name: increment-decrement
40+
- name: indent-error-flow
41+
- name: range
42+
- name: range-val-address
43+
- name: range-val-in-closure
44+
- name: receiver-naming
45+
- name: redefines-builtin-id
46+
- name: superfluous-else
47+
- name: time-naming
48+
- name: unexported-return
49+
- name: unreachable-code
50+
- name: unused-parameter
51+
- name: var-declaration
52+
- name: var-naming
53+
exclusions:
54+
generated: lax
55+
paths:
56+
- third_party$
57+
- builtin$
58+
- examples$
59+
formatters:
60+
enable:
61+
- goimports
62+
exclusions:
63+
generated: lax
64+
paths:
65+
- third_party$
66+
- builtin$
67+
- examples$

build.sh

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright 2025 Google LLC.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http=//www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
# Set SCRIPT_DIR to the current directory of this file.
18+
SCRIPT_DIR=$(cd -P "$(dirname "$0")" >/dev/null 2>&1 && pwd)
19+
SCRIPT_FILE="${SCRIPT_DIR}/$(basename "$0")"
20+
21+
##
22+
## Local Development
23+
##
24+
## These functions should be used to run the local development process
25+
##
26+
27+
## clean - Cleans the build output
28+
function clean() {
29+
if [[ -d '.tools' ]] ; then
30+
rm -rf .tools
31+
fi
32+
}
33+
34+
## build - Builds the project without running tests.
35+
function build() {
36+
go build ./...
37+
}
38+
39+
## test - Runs local unit tests.
40+
function test() {
41+
go test -v -race -cover -short
42+
}
43+
44+
## e2e - Runs end-to-end integration tests.
45+
function e2e() {
46+
if [[ ! -f .envrc ]] ; then
47+
write_e2e_env .envrc
48+
fi
49+
source .envrc
50+
e2e_ci
51+
}
52+
53+
# e2e_ci - Run end-to-end integration tests in the CI system.
54+
# This assumes that the secrets in the env vars are already set.
55+
function e2e_ci() {
56+
go test -race -v ./... | tee test_results.txt
57+
}
58+
59+
function get_golang_tool() {
60+
name="$1"
61+
github_repo="$2"
62+
package="$3"
63+
64+
# Download goimports tool
65+
version=$(curl -s "https://api.github.com/repos/$github_repo/tags" | jq -r '.[].name' | head -n 1)
66+
mkdir -p "$SCRIPT_DIR/.tools"
67+
cmd="$SCRIPT_DIR/.tools/$name"
68+
versioned_cmd="$SCRIPT_DIR/.tools/$name-$version"
69+
if [[ ! -f "$versioned_cmd" ]] ; then
70+
GOBIN="$SCRIPT_DIR/.tools" go install "$package@$version"
71+
mv "$cmd" "$versioned_cmd"
72+
if [[ -f "$cmd" ]] ; then
73+
unlink "$cmd"
74+
fi
75+
ln -s "$versioned_cmd" "$cmd"
76+
fi
77+
}
78+
79+
## fix - Fixes code format.
80+
function fix() {
81+
# run code formatting
82+
get_golang_tool 'goimports' 'golang/tools' 'golang.org/x/tools/cmd/goimports'
83+
".tools/goimports" -w .
84+
go mod tidy
85+
go fmt ./...
86+
}
87+
88+
## lint - runs the linters
89+
function lint() {
90+
# run lint checks
91+
get_golang_tool 'golangci-lint' 'golangci/golangci-lint' 'github.com/golangci/golangci-lint/v2/cmd/golangci-lint'
92+
".tools/golangci-lint" run --timeout 3m
93+
94+
# Check the commit includes a go.mod that is fully
95+
# up to date.
96+
fix
97+
if [[ -d "$SCRIPT_DIR/.git" ]] ; then
98+
git diff --exit-code
99+
fi
100+
}
101+
102+
# lint_ci - runs lint in the CI build job, exiting with an error code if lint fails.
103+
function lint_ci() {
104+
lint # run lint
105+
git diff --exit-code # fail if any files changed
106+
}
107+
108+
## deps - updates project dependencies to latest
109+
function deps() {
110+
go get -u ./...
111+
go get -t -u ./...
112+
113+
# Update the image label in the dockerfiles
114+
for n in Dockerfile Dockerfile.* ; do
115+
dockerfile_from_deps "$n"
116+
done
117+
}
118+
119+
# find
120+
function dockerfile_from_deps() {
121+
# FROM gcr.io/distroless/static:nonroot@sha256:627d6c5a23ad24e6bdff827f16c7b60e0289029b0c79e9f7ccd54ae3279fb45f
122+
# curl -X GET https://gcr.io/v2/distroless/static/manifests/nonroot
123+
file=$1
124+
125+
# Get the last FROM statement from the dockerfile
126+
# those ar
127+
fromLine=$(grep "FROM" $1 | tail -n1)
128+
imageUrl="${fromLine#FROM *}"
129+
130+
# If the image URL does not contain a hash, then don't do anything.
131+
if [[ $imageUrl != *@* ]] ; then
132+
echo "Image does not contain a digest, ignoring"
133+
return
134+
fi
135+
136+
oldDigest="${imageUrl#*@}" #after the '@'
137+
imageWithoutHash="${imageUrl%%@sha256*}" #before the '@sha256'
138+
imageName="${imageWithoutHash%%:*}" #before the ':'
139+
140+
imageLabel="${imageWithoutHash#*:}" #after the ':'
141+
# If none found, use "latest" as the label
142+
if [[ "$imageLabel" == "$imageName" ]] ; then
143+
imageLabel=latest
144+
fi
145+
146+
imageRepo="${imageName%%/*}" #first part of the image name path, may be a repo hostname
147+
if [[ "$imageRepo" == *.* ]]; then
148+
imageName="${imageName#*/}" # trim repo name host from imageName
149+
manifestUrl="https://${imageRepo}/v2/${imageName}/manifests/${imageLabel}"
150+
digest=$(curl -X GET "$manifestUrl" | \
151+
jq -r '.manifests[] | select(.platform.architecture=="amd64" and .platform.os=="linux") | .digest')
152+
153+
else
154+
# registry-1.docker.io requires a token
155+
docker_io_token=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/alpine:pull" | jq -r .token)
156+
manifestUrl="https://registry-1.docker.io/v2/${imageName}/manifests/${imageLabel}"
157+
digest=$(curl -s -H "Authorization: Bearer $docker_io_token" \
158+
-H "Accept: application/vnd.docker.distribution.manifest.list.v2+json" \
159+
https://registry-1.docker.io/v2/library/alpine/manifests/3 | \
160+
jq -r '.manifests[] | select(.platform.architecture=="amd64" and .platform.os=="linux") | .digest')
161+
fi
162+
163+
if [[ "$oldDigest" == "$digest" ]] ; then
164+
echo "No update to image to $file"
165+
else
166+
echo "Updating docker image to $file to $digest"
167+
set -x
168+
sed -i "" "s/$oldDigest/$digest/g" "$file"
169+
fi
170+
171+
}
172+
173+
# write_e2e_env - Loads secrets from the gcloud project and writes
174+
# them to target/e2e.env to run e2e tests.
175+
function write_e2e_env(){
176+
# All secrets used by the e2e tests in the form <env_name>=<secret_name>
177+
secret_vars=(
178+
MYSQL_CONNECTION_NAME=MYSQL_CONNECTION_NAME
179+
MYSQL_USER=MYSQL_USER
180+
MYSQL_PASS=MYSQL_PASS
181+
MYSQL_DB=MYSQL_DB
182+
MYSQL_MCP_CONNECTION_NAME=MYSQL_MCP_CONNECTION_NAME
183+
MYSQL_MCP_PASS=MYSQL_MCP_PASS
184+
POSTGRES_CONNECTION_NAME=POSTGRES_CONNECTION_NAME
185+
POSTGRES_USER=POSTGRES_USER
186+
POSTGRES_USER_IAM=POSTGRES_USER_IAM
187+
POSTGRES_PASS=POSTGRES_PASS
188+
POSTGRES_DB=POSTGRES_DB
189+
POSTGRES_CAS_CONNECTION_NAME=POSTGRES_CAS_CONNECTION_NAME
190+
POSTGRES_CAS_PASS=POSTGRES_CAS_PASS
191+
POSTGRES_CUSTOMER_CAS_CONNECTION_NAME=POSTGRES_CUSTOMER_CAS_CONNECTION_NAME
192+
POSTGRES_CUSTOMER_CAS_PASS=POSTGRES_CUSTOMER_CAS_PASS
193+
POSTGRES_CUSTOMER_CAS_DOMAIN_NAME=POSTGRES_CUSTOMER_CAS_DOMAIN_NAME
194+
POSTGRES_MCP_CONNECTION_NAME=POSTGRES_MCP_CONNECTION_NAME
195+
POSTGRES_MCP_PASS=POSTGRES_MCP_PASS
196+
SQLSERVER_CONNECTION_NAME=SQLSERVER_CONNECTION_NAME
197+
SQLSERVER_USER=SQLSERVER_USER
198+
SQLSERVER_PASS=SQLSERVER_PASS
199+
SQLSERVER_DB=SQLSERVER_DB
200+
IMPERSONATED_USER=IMPERSONATED_USER
201+
)
202+
203+
if [[ -z "$TEST_PROJECT" ]] ; then
204+
echo "Set TEST_PROJECT environment variable to the project containing"
205+
echo "the e2e test suite secrets."
206+
exit 1
207+
fi
208+
209+
local_user=$(gcloud auth list --format 'value(account)' | tr -d '\n')
210+
211+
echo "Getting test secrets from $TEST_PROJECT into $1"
212+
{
213+
for env_name in "${secret_vars[@]}" ; do
214+
env_var_name="${env_name%%=*}"
215+
secret_name="${env_name##*=}"
216+
set -x
217+
val=$(gcloud secrets versions access latest --project "$TEST_PROJECT" --secret="$secret_name")
218+
echo "export $env_var_name='$val'"
219+
done
220+
221+
# Set IAM User env vars to the local gcloud user
222+
echo "export MYSQL_IAM_USER='${local_user%%@*}'"
223+
echo "export POSTGRES_USER_IAM='$local_user'"
224+
} > "$1"
225+
226+
}
227+
228+
## help - prints the help details
229+
##
230+
function help() {
231+
# This will print the comments beginning with ## above each function
232+
# in this file.
233+
234+
echo "build.sh <command> <arguments>"
235+
echo
236+
echo "Commands to assist with local development and CI builds."
237+
echo
238+
echo "Commands:"
239+
echo
240+
grep -e '^##' "$SCRIPT_FILE" | sed -e 's/##/ /'
241+
}
242+
243+
set -euo pipefail
244+
245+
# Check CLI Arguments
246+
if [[ "$#" -lt 1 ]] ; then
247+
help
248+
exit 1
249+
fi
250+
251+
cd "$SCRIPT_DIR"
252+
253+
"$@"
254+

cmd/gendocs/gen_cloud-sql-proxy_docs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,6 @@ func main() {
4646

4747
cloudSQLProxy := cmd.NewCommand()
4848
cloudSQLProxy.Execute()
49-
cloudSQLProxy.Command.DisableAutoGenTag = true
49+
cloudSQLProxy.DisableAutoGenTag = true
5050
doc.GenMarkdownTree(cloudSQLProxy.Command, outDir)
5151
}

internal/proxy/fuse_darwin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func SupportsFUSE() error {
3434
if _, err := os.Stat(macfusePath); err != nil {
3535
// if that fails, check for osxfuse next
3636
if _, err := os.Stat(osxfusePath); err != nil {
37-
return errors.New("failed to find osxfuse or macfuse: verify FUSE installation and try again (see https://osxfuse.github.io).")
37+
return errors.New("failed to find osxfuse or macfuse: verify FUSE installation and try again (see https://osxfuse.github.io)")
3838
}
3939
}
4040
return nil

0 commit comments

Comments
 (0)