From bbe9cae118a91eda06cc814045951dfe32e8a010 Mon Sep 17 00:00:00 2001 From: Kyle Montgomery Date: Thu, 9 Apr 2026 12:23:03 +0000 Subject: [PATCH 01/14] Prototype skillgrade for evals --- .env.example | 4 ++ .gitignore | 1 + Dockerfile.eval | 78 ++++++++++++++++++++++++++++ eval-entrypoint.sh | 21 ++++++++ eval.yaml | 83 ++++++++++++++++++++++++++++++ graders/teardown-gcs.sh | 44 ++++++++++++++++ graders/teardown.sh | 8 +++ graders/validate-deployment.sh | 0 graders/validate-gcs-deployment.sh | 72 ++++++++++++++++++++++++++ graders/validate-pipeline.sh | 8 +++ graders/validate-rubric.md | 1 + 11 files changed, 320 insertions(+) create mode 100644 .env.example create mode 100644 Dockerfile.eval create mode 100644 eval-entrypoint.sh create mode 100644 eval.yaml create mode 100755 graders/teardown-gcs.sh create mode 100755 graders/teardown.sh create mode 100644 graders/validate-deployment.sh create mode 100755 graders/validate-gcs-deployment.sh create mode 100644 graders/validate-pipeline.sh create mode 100644 graders/validate-rubric.md diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..af809af --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +PROJECT_ID= +# Used by eval-entrypoint.sh +GOOGLE_APPLICATION_CREDENTIALS_CONTENTS= +GCS_BUCKET= diff --git a/.gitignore b/.gitignore index ea3d1a8..c6e335c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ server # GitHub App credentials gha-creds-*.json +.env diff --git a/Dockerfile.eval b/Dockerfile.eval new file mode 100644 index 0000000..5200f08 --- /dev/null +++ b/Dockerfile.eval @@ -0,0 +1,78 @@ +# Stage 1: Build the MCP Server +FROM debian:sid AS builder + +WORKDIR /app + +RUN apt-get update && apt-get install -y \ + curl \ + git \ + sudo \ + golang-go \ + && rm -rf /var/lib/apt/lists/* +COPY cicd-mcp-server/ ./cicd-mcp-server/ +COPY lib/ ./lib/ +COPY build.sh ./ + +RUN chmod +x build.sh +RUN ./build.sh + +# Stage 2: Build the eval image with dependencies +FROM node:20-slim + +RUN apt-get update && apt-get install -y \ + curl \ + procps \ + python3 \ + unzip \ + git \ + && rm -rf /var/lib/apt/lists/* \ + && ln -sf /bin/bash /bin/sh + +# gcloud +RUN curl -sSL https://sdk.cloud.google.com | bash +ENV PATH=${PATH}:/root/google-cloud-sdk/bin + +# Terraform +RUN curl -LO https://releases.hashicorp.com/terraform/1.14.8/terraform_1.14.8_linux_amd64.zip \ + && unzip terraform_1.14.8_linux_amd64.zip \ + && mv terraform /usr/local/bin/ \ + && rm terraform_1.14.8_linux_amd64.zip + +# Configure cicd MCP server +COPY --from=builder /app/cicd-mcp-server/cicd-mcp-server /usr/local/bin/cicd-mcp-server +RUN mkdir -p /root/.gemini +COPY <> /root/.bashrc + +ENTRYPOINT ["/usr/local/bin/eval-entrypoint.sh"] + +CMD ["bash"] diff --git a/eval-entrypoint.sh b/eval-entrypoint.sh new file mode 100644 index 0000000..7a26252 --- /dev/null +++ b/eval-entrypoint.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -e + +ENV_FILE="/etc/eval-env.sh" +echo "#!/bin/bash" > "$ENV_FILE" + +if [ -n "$GOOGLE_APPLICATION_CREDENTIALS_CONTENTS" ]; then + TMP_FILE=$(mktemp /tmp/gcp-XXXXXX.json) + echo "$GOOGLE_APPLICATION_CREDENTIALS_CONTENTS" > "$TMP_FILE" + export GOOGLE_APPLICATION_CREDENTIALS="$TMP_FILE" + echo "export GOOGLE_APPLICATION_CREDENTIALS=\"$TMP_FILE\"" >> "$ENV_FILE" +fi + +TOKEN=$(gcloud auth application-default print-access-token) +export CLOUDSDK_AUTH_ACCESS_TOKEN="$TOKEN" +echo "export CLOUDSDK_AUTH_ACCESS_TOKEN=\"$TOKEN\"" >> "$ENV_FILE" + +chmod +x "$ENV_FILE" + +exec "$@" + diff --git a/eval.yaml b/eval.yaml new file mode 100644 index 0000000..bcfab2b --- /dev/null +++ b/eval.yaml @@ -0,0 +1,83 @@ +version: "1" + +# See https://github.com/mgechev/skillgrade + +# Running evals: +# - Create local .env file by filling in values from .env.example +# - Install skillgrade: npm i -g skillgrade +# - Run evals: +# - GEMINI_API_KEY= skillgrade +# - GEMINI_API_KEY= skillgrade --name=task1,task2 +# - View results: +# - skillgrade preview browser + + +defaults: + agent: gemini + provider: docker + trials: 1 # TODO increase trials + timeout: 300 + threshold: 0.8 # For --ci mode + grader_model: gemini-3-flash-preview # default LLM grader model + docker: + base: cicd-evals:latest + +tasks: + - name: deploy-static-site-gcs + instruction: | + Deploy this static site in ./example to a Google Cloud Storage bucket in region 'us-central1'. + The site should be built by using tinyjam itself. + + The bucket name will be available as an environment variable $GCS_BUCKET. + The project id will be available as an environment variable $PROJECT_ID. + + timeout: 600 + + graders: + - type: deterministic + setup: | + git clone https://github.com/mourner/tinyjam . + run: graders/validate-gcs-deployment.sh + weight: 1.0 + - type: deterministic + run: graders/teardown-gcs.sh + weight: 0 + + + - name: design-cloud-run-pipeline-python + instruction: | + Design a CI/CD pipeline to deploy this application using Terraform. This should include steps + to lint, build, test and finally deploy to Cloud Run. + + graders: + - type: deterministic + setup: | + git clone https://github.com/yeshwanth1993/chefs-companion.git . && \ + rm Dockerfile cloudbuild.yaml + run: graders/validate-pipeline.sh + weight: 0.7 + - type: llm_rubric + rubric: graders/validate-rubric.md + weight: 0.3 + - type: deterministic + run: graders/teardown.sh + weight: 0 + + - name: design-cloud-run-pipeline-nodejs + instruction: | + Design a CI/CD pipeline to deploy this application using Terraform. This should include steps + to lint, build, test and finally deploy to Cloud Run. + + graders: + - type: deterministic + setup: | + git clone https://github.com/mourner/tinyjam . && \ + rm Dockerfile cloudbuild.yaml + run: graders/validate-pipeline.sh + weight: 0.7 + - type: llm_rubric + rubric: graders/validate-rubric.md + weight: 0.3 + - type: deterministic + run: graders/teardown.sh + weight: 0 \ No newline at end of file diff --git a/graders/teardown-gcs.sh b/graders/teardown-gcs.sh new file mode 100755 index 0000000..8eaefe4 --- /dev/null +++ b/graders/teardown-gcs.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Check if GCS_BUCKET is set +if [ -z "$GCS_BUCKET" ]; then + cat < /dev/null + +# Delete the bucket +gcloud storage buckets delete gs://$GCS_BUCKET $PROJECT_ARG --quiet &> /dev/null + +# Check if the bucket still exists +if gcloud storage buckets describe gs://$GCS_BUCKET $PROJECT_ARG &> /dev/null; then + cat < /dev/null; then + passed=$((passed + 1)) + c1_pass=true + c1_msg="Bucket $GCS_BUCKET exists" + + # Check 2: Bucket contains files + FILES=$(gcloud storage ls gs://$GCS_BUCKET 2>/dev/null) + if [ -n "$FILES" ]; then + passed=$((passed + 1)) + c2_pass=true + c2_msg="Bucket contains files" + + # Check 3: Public access + # Find a file to test + TARGET_FILE="" + if echo "$FILES" | grep -q "gs://$GCS_BUCKET/index.html"; then + TARGET_FILE="index.html" + else + TARGET_FILE=$(echo "$FILES" | head -n 1 | sed "s|gs://$GCS_BUCKET/||") + fi + + if [ -n "$TARGET_FILE" ]; then + URL="https://storage.googleapis.com/$GCS_BUCKET/$TARGET_FILE" + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$URL") + + if [ "$HTTP_CODE" = "200" ]; then + passed=$((passed + 1)) + c3_pass=true + c3_msg="Successfully accessed $URL (HTTP 200)" + else + c3_msg="Failed to access $URL (HTTP $HTTP_CODE)" + fi + else + c3_msg="Could not determine a target file to test" + fi + else + c2_msg="Bucket is empty" + fi +fi + +# Calculate score using awk +score=$(awk "BEGIN {printf \"%.2f\", $passed/$total}") + +# Output JSON +echo "{\"score\":$score,\"details\":\"$passed/$total checks passed\",\"checks\":[{\"name\":\"bucket-exists\",\"passed\":$c1_pass,\"message\":\"$c1_msg\"},{\"name\":\"contains-files\",\"passed\":$c2_pass,\"message\":\"$c2_msg\"},{\"name\":\"public-access\",\"passed\":$c3_pass,\"message\":\"$c3_msg\"}]}" diff --git a/graders/validate-pipeline.sh b/graders/validate-pipeline.sh new file mode 100644 index 0000000..a32dbfb --- /dev/null +++ b/graders/validate-pipeline.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +cat < Date: Thu, 9 Apr 2026 12:35:42 +0000 Subject: [PATCH 02/14] Add instruction for building docker image --- eval.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eval.yaml b/eval.yaml index bcfab2b..06ad341 100644 --- a/eval.yaml +++ b/eval.yaml @@ -4,6 +4,8 @@ version: "1" # Running evals: # - Create local .env file by filling in values from .env.example +# - Build the base docker image +# - docker build -t cicd-evals:latest . # - Install skillgrade: npm i -g skillgrade # - Run evals: # - GEMINI_API_KEY= skillgrade From 69acd3aa248fd47bd45b3db109477b96b514bf5e Mon Sep 17 00:00:00 2001 From: Kyle Montgomery Date: Thu, 9 Apr 2026 16:30:23 +0000 Subject: [PATCH 03/14] Using fork of skillgrade we a few new features --- eval.yaml | 45 +++++++++++++++++++++-------------------- graders/teardown-gcs.sh | 21 +++---------------- graders/teardown.sh | 7 +------ 3 files changed, 27 insertions(+), 46 deletions(-) diff --git a/eval.yaml b/eval.yaml index 06ad341..1604575 100644 --- a/eval.yaml +++ b/eval.yaml @@ -6,9 +6,10 @@ version: "1" # - Create local .env file by filling in values from .env.example # - Build the base docker image # - docker build -t cicd-evals:latest . -# - Install skillgrade: npm i -g skillgrade -# - Run evals: +# - Install skillgrade: npm i -g @kmonty/skillgrade@latest +# - Run all evals: # - GEMINI_API_KEY= skillgrade +# - Run specific evals: # - GEMINI_API_KEY= skillgrade --name=task1,task2 # - View results: # - skillgrade preview browser @@ -25,6 +26,8 @@ defaults: base: cicd-evals:latest tasks: + + # Evals for simple static site: https://github.com/sdlc-graph/tinyjam.git - name: deploy-static-site-gcs instruction: | Deploy this static site in ./example to a Google Cloud Storage bucket in region 'us-central1'. @@ -35,51 +38,49 @@ tasks: timeout: 600 + trialConfig: + setup: git clone https://github.com/sdlc-graph/tinyjam.git + cleanup: graders/teardown-gcs.sh + graders: - type: deterministic - setup: | - git clone https://github.com/mourner/tinyjam . run: graders/validate-gcs-deployment.sh weight: 1.0 - - type: deterministic - run: graders/teardown-gcs.sh - weight: 0 - - + - name: design-cloud-run-pipeline-python instruction: | Design a CI/CD pipeline to deploy this application using Terraform. This should include steps to lint, build, test and finally deploy to Cloud Run. + + trialConfig: + setup: | + git clone https://github.com/sdlc-graph/chefs-companion.git && \ + rm chefs-companion/Dockerfile chefs-companion/cloudbuild.yaml + cleanup: graders/teardown-cloud-run.sh graders: - type: deterministic - setup: | - git clone https://github.com/yeshwanth1993/chefs-companion.git . && \ - rm Dockerfile cloudbuild.yaml run: graders/validate-pipeline.sh weight: 0.7 - type: llm_rubric rubric: graders/validate-rubric.md weight: 0.3 - - type: deterministic - run: graders/teardown.sh - weight: 0 - name: design-cloud-run-pipeline-nodejs instruction: | Design a CI/CD pipeline to deploy this application using Terraform. This should include steps to lint, build, test and finally deploy to Cloud Run. + trialConfig: + setup: | + git clone https://github.com/sdlc-graph/chefs-companion.git && \ + rm chefs-companion/Dockerfile chefs-companion/cloudbuild.yaml + cleanup: graders/teardown-cloud-run.sh + graders: - type: deterministic - setup: | - git clone https://github.com/mourner/tinyjam . && \ - rm Dockerfile cloudbuild.yaml run: graders/validate-pipeline.sh weight: 0.7 - type: llm_rubric rubric: graders/validate-rubric.md - weight: 0.3 - - type: deterministic - run: graders/teardown.sh - weight: 0 \ No newline at end of file + weight: 0.3 \ No newline at end of file diff --git a/graders/teardown-gcs.sh b/graders/teardown-gcs.sh index 8eaefe4..9c01b9e 100755 --- a/graders/teardown-gcs.sh +++ b/graders/teardown-gcs.sh @@ -2,12 +2,7 @@ # Check if GCS_BUCKET is set if [ -z "$GCS_BUCKET" ]; then - cat <&2 exit 1 fi @@ -26,19 +21,9 @@ gcloud storage buckets delete gs://$GCS_BUCKET $PROJECT_ARG --quiet &> /dev/null # Check if the bucket still exists if gcloud storage buckets describe gs://$GCS_BUCKET $PROJECT_ARG &> /dev/null; then - cat <&2 exit 1 else - cat < Date: Thu, 9 Apr 2026 18:22:39 +0000 Subject: [PATCH 04/14] Updating to leverage new skillgrade features --- Dockerfile.eval | 5 ----- eval-entrypoint.sh | 18 +++++++++--------- eval.yaml | 23 ++++++++++++++++------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/Dockerfile.eval b/Dockerfile.eval index 5200f08..71e94da 100644 --- a/Dockerfile.eval +++ b/Dockerfile.eval @@ -60,11 +60,6 @@ COPY < "$ENV_FILE" -if [ -n "$GOOGLE_APPLICATION_CREDENTIALS_CONTENTS" ]; then - TMP_FILE=$(mktemp /tmp/gcp-XXXXXX.json) - echo "$GOOGLE_APPLICATION_CREDENTIALS_CONTENTS" > "$TMP_FILE" - export GOOGLE_APPLICATION_CREDENTIALS="$TMP_FILE" - echo "export GOOGLE_APPLICATION_CREDENTIALS=\"$TMP_FILE\"" >> "$ENV_FILE" +# Try to get ADC token, but don't fail the script if it fails +if TOKEN=$(gcloud auth application-default print-access-token 2>/tmp/adc-error.log); then + export CLOUDSDK_AUTH_ACCESS_TOKEN="$TOKEN" + echo "export CLOUDSDK_AUTH_ACCESS_TOKEN=\"$TOKEN\"" >> "$ENV_FILE" +else + echo "Warning: Failed to obtain ADC token. Credentials may be invalid." >&2 + echo "Error details saved to /etc/eval-adc-error.log" >&2 + cp /tmp/adc-error.log /etc/eval-adc-error.log + echo "export ADC_AUTH_ERROR=\"true\"" >> "$ENV_FILE" fi -TOKEN=$(gcloud auth application-default print-access-token) -export CLOUDSDK_AUTH_ACCESS_TOKEN="$TOKEN" -echo "export CLOUDSDK_AUTH_ACCESS_TOKEN=\"$TOKEN\"" >> "$ENV_FILE" - chmod +x "$ENV_FILE" exec "$@" diff --git a/eval.yaml b/eval.yaml index 1604575..63a2386 100644 --- a/eval.yaml +++ b/eval.yaml @@ -8,9 +8,9 @@ version: "1" # - docker build -t cicd-evals:latest . # - Install skillgrade: npm i -g @kmonty/skillgrade@latest # - Run all evals: -# - GEMINI_API_KEY= skillgrade +# - GEMINI_API_KEY= skillgrade --no-redact # - Run specific evals: -# - GEMINI_API_KEY= skillgrade --name=task1,task2 +# - GEMINI_API_KEY= skillgrade --name=task1,task2 --no-redact # - View results: # - skillgrade preview browser @@ -19,25 +19,28 @@ defaults: agent: gemini provider: docker trials: 1 # TODO increase trials - timeout: 300 + timeout: 150 threshold: 0.8 # For --ci mode grader_model: gemini-3-flash-preview # default LLM grader model docker: base: cicd-evals:latest + env: + GOOGLE_APPLICATION_CREDENTIALS: /tmp/keys/adc.json + environment: + mounts: + - ~/.config/gcloud/application_default_credentials.json:/tmp/keys/adc.json:ro tasks: # Evals for simple static site: https://github.com/sdlc-graph/tinyjam.git - name: deploy-static-site-gcs instruction: | - Deploy this static site in ./example to a Google Cloud Storage bucket in region 'us-central1'. + Deploy this static site in .tinyjam/example to a Google Cloud Storage bucket in region 'us-central1'. The site should be built by using tinyjam itself. The bucket name will be available as an environment variable $GCS_BUCKET. The project id will be available as an environment variable $PROJECT_ID. - timeout: 600 - trialConfig: setup: git clone https://github.com/sdlc-graph/tinyjam.git cleanup: graders/teardown-gcs.sh @@ -45,7 +48,13 @@ tasks: graders: - type: deterministic run: graders/validate-gcs-deployment.sh - weight: 1.0 + weight: 0.5 + - type: tool_usage + expectedTools: + - name: activate_skill + args: + name: google-cicd-deploy + weight: 0.5 - name: design-cloud-run-pipeline-python instruction: | From e0a6982495c88cc145892e87eeb31d3192322d1b Mon Sep 17 00:00:00 2001 From: Kyle Montgomery Date: Thu, 9 Apr 2026 18:27:22 +0000 Subject: [PATCH 05/14] Update skillgraph reference to our fork --- eval.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eval.yaml b/eval.yaml index 63a2386..49fb56a 100644 --- a/eval.yaml +++ b/eval.yaml @@ -1,6 +1,6 @@ version: "1" -# See https://github.com/mgechev/skillgrade +# See https://github.com/sdlc-graph/skillgrade # Running evals: # - Create local .env file by filling in values from .env.example From d13491eff17693f497b0212218f5d6b0ca87f2ad Mon Sep 17 00:00:00 2001 From: Kyle Montgomery Date: Thu, 9 Apr 2026 18:28:41 +0000 Subject: [PATCH 06/14] Update ADC env variable comment for CI --- .env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index af809af..37af20f 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ PROJECT_ID= -# Used by eval-entrypoint.sh -GOOGLE_APPLICATION_CREDENTIALS_CONTENTS= +# In CI we should unset this to rely on metadata server instead +GOOGLE_APPLICATION_CREDENTIALS= GCS_BUCKET= From bb966973fafd9ee677b212dc1cf39061f61c8363 Mon Sep 17 00:00:00 2001 From: Kyle Montgomery Date: Thu, 9 Apr 2026 21:08:18 +0000 Subject: [PATCH 07/14] Adding cloud run deployment eval --- Dockerfile.eval | 7 +- eval.yaml | 98 +++++++++++++++-------- graders/validate-deployment.sh | 0 graders/validate-gcs-deployment.sh | 72 ----------------- scripts/teardown-cloud-run.sh | 29 +++++++ {graders => scripts}/teardown-gcs.sh | 0 {graders => scripts}/teardown.sh | 0 scripts/validate-cloud-run-deployment.sh | 77 ++++++++++++++++++ scripts/validate-gcs-deployment.sh | 82 +++++++++++++++++++ {graders => scripts}/validate-pipeline.sh | 0 {graders => scripts}/validate-rubric.md | 0 11 files changed, 259 insertions(+), 106 deletions(-) delete mode 100644 graders/validate-deployment.sh delete mode 100755 graders/validate-gcs-deployment.sh create mode 100755 scripts/teardown-cloud-run.sh rename {graders => scripts}/teardown-gcs.sh (100%) rename {graders => scripts}/teardown.sh (100%) create mode 100755 scripts/validate-cloud-run-deployment.sh create mode 100755 scripts/validate-gcs-deployment.sh rename {graders => scripts}/validate-pipeline.sh (100%) rename {graders => scripts}/validate-rubric.md (100%) diff --git a/Dockerfile.eval b/Dockerfile.eval index 71e94da..913d51b 100644 --- a/Dockerfile.eval +++ b/Dockerfile.eval @@ -41,13 +41,16 @@ RUN curl -LO https://releases.hashicorp.com/terraform/1.14.8/terraform_1.14.8_li # Configure cicd MCP server COPY --from=builder /app/cicd-mcp-server/cicd-mcp-server /usr/local/bin/cicd-mcp-server RUN mkdir -p /root/.gemini -COPY < /dev/null; then - passed=$((passed + 1)) - c1_pass=true - c1_msg="Bucket $GCS_BUCKET exists" - - # Check 2: Bucket contains files - FILES=$(gcloud storage ls gs://$GCS_BUCKET 2>/dev/null) - if [ -n "$FILES" ]; then - passed=$((passed + 1)) - c2_pass=true - c2_msg="Bucket contains files" - - # Check 3: Public access - # Find a file to test - TARGET_FILE="" - if echo "$FILES" | grep -q "gs://$GCS_BUCKET/index.html"; then - TARGET_FILE="index.html" - else - TARGET_FILE=$(echo "$FILES" | head -n 1 | sed "s|gs://$GCS_BUCKET/||") - fi - - if [ -n "$TARGET_FILE" ]; then - URL="https://storage.googleapis.com/$GCS_BUCKET/$TARGET_FILE" - HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$URL") - - if [ "$HTTP_CODE" = "200" ]; then - passed=$((passed + 1)) - c3_pass=true - c3_msg="Successfully accessed $URL (HTTP 200)" - else - c3_msg="Failed to access $URL (HTTP $HTTP_CODE)" - fi - else - c3_msg="Could not determine a target file to test" - fi - else - c2_msg="Bucket is empty" - fi -fi - -# Calculate score using awk -score=$(awk "BEGIN {printf \"%.2f\", $passed/$total}") - -# Output JSON -echo "{\"score\":$score,\"details\":\"$passed/$total checks passed\",\"checks\":[{\"name\":\"bucket-exists\",\"passed\":$c1_pass,\"message\":\"$c1_msg\"},{\"name\":\"contains-files\",\"passed\":$c2_pass,\"message\":\"$c2_msg\"},{\"name\":\"public-access\",\"passed\":$c3_pass,\"message\":\"$c3_msg\"}]}" diff --git a/scripts/teardown-cloud-run.sh b/scripts/teardown-cloud-run.sh new file mode 100755 index 0000000..6e7e737 --- /dev/null +++ b/scripts/teardown-cloud-run.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status. +set -e + +# Check for required environment variables +if [ -z "$CLOUD_RUN_SERVICE" ]; then + echo "Error: CLOUD_RUN_SERVICE environment variable is not set." + exit 1 +fi + +if [ -z "$PROJECT_ID" ]; then + echo "Error: PROJECT_ID environment variable is not set." + exit 1 +fi + +if [ -z "$REGION" ]; then + echo "Error: REGION environment variable is not set." + exit 1 +fi + +echo "Deleting Cloud Run service $CLOUD_RUN_SERVICE in project $PROJECT_ID and region $REGION..." + +gcloud run services delete "$CLOUD_RUN_SERVICE" \ + --project="$PROJECT_ID" \ + --region="$REGION" \ + --quiet + +echo "Cloud Run service $CLOUD_RUN_SERVICE deletion command completed." diff --git a/graders/teardown-gcs.sh b/scripts/teardown-gcs.sh similarity index 100% rename from graders/teardown-gcs.sh rename to scripts/teardown-gcs.sh diff --git a/graders/teardown.sh b/scripts/teardown.sh similarity index 100% rename from graders/teardown.sh rename to scripts/teardown.sh diff --git a/scripts/validate-cloud-run-deployment.sh b/scripts/validate-cloud-run-deployment.sh new file mode 100755 index 0000000..a4bb7df --- /dev/null +++ b/scripts/validate-cloud-run-deployment.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# Support both PROJECT_NAME and PROJECT_ID +PROJECT_NAME=${PROJECT_NAME:-$PROJECT_ID} + +# Initialize checks +CHECK_EXISTS="false" +MSG_EXISTS="Not checked" +CHECK_REACHABLE="false" +MSG_REACHABLE="Not checked" + +# Check for required environment variables +MISSING_VARS=() +[ -z "$CLOUD_RUN_SERVICE" ] && MISSING_VARS+=("CLOUD_RUN_SERVICE") +[ -z "$PROJECT_NAME" ] && MISSING_VARS+=("PROJECT_NAME/PROJECT_ID") +[ -z "$REGION" ] && MISSING_VARS+=("REGION") + +if [ ${#MISSING_VARS[@]} -ne 0 ]; then + MSG_EXISTS="Missing environment variables: ${MISSING_VARS[*]}" +else + # 1. Check if service exists + if gcloud run services describe "$CLOUD_RUN_SERVICE" --project="$PROJECT_NAME" --region="$REGION" &>/dev/null; then + CHECK_EXISTS="true" + MSG_EXISTS="Service exists" + + + # 3. Check Reachable + URL=$(gcloud run services describe "$CLOUD_RUN_SERVICE" \ + --project="$PROJECT_NAME" \ + --region="$REGION" \ + --format='value(status.url)') + + if [ -n "$URL" ]; then + CURL_OPTS="-s -o /dev/null -w %{http_code}" + HTTP_STATUS=$(curl $CURL_OPTS "$URL") + + if [ "$HTTP_STATUS" == "000" ]; then + CHECK_REACHABLE="false" + MSG_REACHABLE="Could not connect to service URL" + elif [[ "$HTTP_STATUS" =~ ^5 ]]; then + CHECK_REACHABLE="false" + MSG_REACHABLE="Service returned server error (HTTP $HTTP_STATUS)" + else + CHECK_REACHABLE="true" + MSG_REACHABLE="Service is reachable (HTTP $HTTP_STATUS)" + fi + else + CHECK_REACHABLE="false" + MSG_REACHABLE="Service URL not found" + fi + + else + CHECK_EXISTS="false" + MSG_EXISTS="Service does not exist or is not accessible" + MSG_REACHABLE="Skipped: Service does not exist" + fi +fi + +# Calculate score +TOTAL_CHECKS=2 +PASSED_CHECKS=0 +[ "$CHECK_EXISTS" == "true" ] && ((PASSED_CHECKS++)) +[ "$CHECK_REACHABLE" == "true" ] && ((PASSED_CHECKS++)) + +SCORE=$(awk "BEGIN {printf \"%.2f\", $PASSED_CHECKS / $TOTAL_CHECKS}") + +# Construct JSON +cat < /dev/null; then + CHECK_EXISTS="true" + MSG_EXISTS="Bucket $GCS_BUCKET exists" + + # Check 2: Bucket contains files + FILES=$(gcloud storage ls gs://$GCS_BUCKET 2>/dev/null) + if [ -n "$FILES" ]; then + CHECK_CONTAINS="true" + MSG_CONTAINS="Bucket contains files" + + # Check 3: Public access + # Find a file to test + TARGET_FILE="" + if echo "$FILES" | grep -q "gs://$GCS_BUCKET/index.html"; then + TARGET_FILE="index.html" + else + TARGET_FILE=$(echo "$FILES" | head -n 1 | sed "s|gs://$GCS_BUCKET/||") + fi + + if [ -n "$TARGET_FILE" ]; then + URL="https://storage.googleapis.com/$GCS_BUCKET/$TARGET_FILE" + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$URL") + + if [ "$HTTP_CODE" = "200" ]; then + CHECK_PUBLIC="true" + MSG_PUBLIC="Successfully accessed $URL (HTTP 200)" + else + MSG_PUBLIC="Failed to access $URL (HTTP $HTTP_CODE)" + fi + else + MSG_PUBLIC="Could not determine a target file to test" + fi + else + MSG_CONTAINS="Bucket is empty" + fi +fi + +# Calculate score +TOTAL_CHECKS=3 +PASSED_CHECKS=0 +[ "$CHECK_EXISTS" == "true" ] && ((PASSED_CHECKS++)) +[ "$CHECK_CONTAINS" == "true" ] && ((PASSED_CHECKS++)) +[ "$CHECK_PUBLIC" == "true" ] && ((PASSED_CHECKS++)) + +SCORE=$(awk "BEGIN {printf \"%.2f\", $PASSED_CHECKS / $TOTAL_CHECKS}") + +# Construct JSON +cat < Date: Fri, 10 Apr 2026 14:06:39 +0000 Subject: [PATCH 08/14] Adding more evals --- Dockerfile.eval | 16 +------ eval-entrypoint.sh | 21 --------- eval.yaml | 102 +++++++++++++++++++++++----------------- scripts/setup_gcloud.sh | 15 ++++++ 4 files changed, 76 insertions(+), 78 deletions(-) delete mode 100644 eval-entrypoint.sh create mode 100755 scripts/setup_gcloud.sh diff --git a/Dockerfile.eval b/Dockerfile.eval index 913d51b..99df937 100644 --- a/Dockerfile.eval +++ b/Dockerfile.eval @@ -25,8 +25,7 @@ RUN apt-get update && apt-get install -y \ python3 \ unzip \ git \ - && rm -rf /var/lib/apt/lists/* \ - && ln -sf /bin/bash /bin/sh + && rm -rf /var/lib/apt/lists/* # gcloud RUN curl -sSL https://sdk.cloud.google.com | bash @@ -62,15 +61,4 @@ COPY <> /root/.bashrc - -ENTRYPOINT ["/usr/local/bin/eval-entrypoint.sh"] - -CMD ["bash"] +CMD ["sh"] diff --git a/eval-entrypoint.sh b/eval-entrypoint.sh deleted file mode 100644 index b710f36..0000000 --- a/eval-entrypoint.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -set -e - -ENV_FILE="/etc/eval-env.sh" -echo "#!/bin/bash" > "$ENV_FILE" - -# Try to get ADC token, but don't fail the script if it fails -if TOKEN=$(gcloud auth application-default print-access-token 2>/tmp/adc-error.log); then - export CLOUDSDK_AUTH_ACCESS_TOKEN="$TOKEN" - echo "export CLOUDSDK_AUTH_ACCESS_TOKEN=\"$TOKEN\"" >> "$ENV_FILE" -else - echo "Warning: Failed to obtain ADC token. Credentials may be invalid." >&2 - echo "Error details saved to /etc/eval-adc-error.log" >&2 - cp /tmp/adc-error.log /etc/eval-adc-error.log - echo "export ADC_AUTH_ERROR=\"true\"" >> "$ENV_FILE" -fi - -chmod +x "$ENV_FILE" - -exec "$@" - diff --git a/eval.yaml b/eval.yaml index 5798b70..0514ac6 100644 --- a/eval.yaml +++ b/eval.yaml @@ -29,6 +29,8 @@ defaults: environment: mounts: - ~/.config/gcloud/application_default_credentials.json:/tmp/keys/adc.json:ro + trialConfig: + setup: scripts/setup_gcloud.sh tasks: @@ -59,7 +61,7 @@ tasks: weight: 0.5 # Evals for deploying simple python application: https://github.com/sdlc-graph/chefs-companion - - name: deploy-cloud-run-pipeline-python + - name: deploy-cloud-run-buildpacks-python instruction: | Deploy the python application in ./chefs-companion to Cloud Run in region 'us-central1'. @@ -67,63 +69,77 @@ tasks: The cloud run service name will be available as an environment variable $CLOUD_RUN_SERVICE. The artifact registry to use will be available as an environment variable $ARTIFACT_REGISTRY. The region to use will be available as an environment variable $REGION. + Use buildpacks for building and deploying the application. timeout: 600 trialConfig: - setup: git clone https://github.com/sdlc-graph/chefs-companion.git + setup: | + git clone -b buildpacks https://github.com/sdlc-graph/chefs-companion.git cleanup: scripts/teardown-cloud-run.sh graders: - type: deterministic run: scripts/validate-cloud-run-deployment.sh - weight: 0.5 - # TODO: confirm these are the correct tools for this repo + weight: 1 + - type: deterministic + run: | + if [ ! -f chefs-companion/Dockerfile ]; then + echo '{"score": 1, "details": "Dockerfile does not exist"}' + else + echo '{"score": 0, "details": "Dockerfile exists"}' + fi + weight: 1 - type: tool_usage expectedTools: - name: activate_skill args: name: google-cicd-deploy - - name: mcp_cicd_create_artifact_repository - name: mcp_cicd_deploy_cloudrun_service_from_source - name: mcp_cicd_scan_code_for_secrets - weight: 0.5 - + weight: 1 + - type: llm_rubric + rubric: The agent must have used buildpacks to build the application + weight: 1 - # - name: design-cloud-run-pipeline-python - # instruction: | - # Design a CI/CD pipeline to deploy this application using Terraform. This should include steps - # to lint, build, test and finally deploy to Cloud Run. + # Evals for deploying simple python application: https://github.com/sdlc-graph/chefs-companion + - name: deploy-cloud-run-no-dockerfile-python + instruction: | + Deploy the python application in ./chefs-companion to Cloud Run in region 'us-central1'. - # trialConfig: - # setup: | - # git clone https://github.com/sdlc-graph/chefs-companion.git && \ - # rm chefs-companion/Dockerfile chefs-companion/cloudbuild.yaml - # cleanup: scripts/teardown-cloud-run.sh - - # graders: - # - type: deterministic - # run: scripts/validate-pipeline.sh - # weight: 0.7 - # - type: llm_rubric - # rubric: scripts/validate-rubric.md - # weight: 0.3 - - # - name: design-cloud-run-pipeline-nodejs - # instruction: | - # Design a CI/CD pipeline to deploy this application using Terraform. This should include steps - # to lint, build, test and finally deploy to Cloud Run. - - # trialConfig: - # setup: | - # git clone https://github.com/sdlc-graph/chefs-companion.git && \ - # rm chefs-companion/Dockerfile chefs-companion/cloudbuild.yaml - # cleanup: scripts/teardown-cloud-run.sh - - # graders: - # - type: deterministic - # run: gradscriptsers/validate-pipeline.sh - # weight: 0.7 - # - type: llm_rubric - # rubric: scripts/validate-rubric.md - # weight: 0.3 \ No newline at end of file + The project id will be available as an environment variable $PROJECT_ID. + The cloud run service name will be available as an environment variable $CLOUD_RUN_SERVICE. + The artifact registry to use will be available as an environment variable $ARTIFACT_REGISTRY. + The region to use will be available as an environment variable $REGION. + Build a customer docker image for the application. + + timeout: 600 + + trialConfig: + setup: | + git clone -b no-dockerfile https://github.com/sdlc-graph/chefs-companion.git + cleanup: scripts/teardown-cloud-run.sh + + graders: + - type: deterministic + run: scripts/validate-cloud-run-deployment.sh + weight: 1 + - type: deterministic + run: | + if [ -f chefs-companion/Dockerfile ]; then + echo '{"score": 1, "details": "Dockerfile exists"}' + else + echo '{"score": 0, "details": "Dockerfile does not exist"}' + fi + weight: 1 + - type: tool_usage + expectedTools: + - name: activate_skill + args: + name: google-cicd-deploy + - name: mcp_cicd_deploy_cloudrun_service_from_source + - name: mcp_cicd_scan_code_for_secrets + weight: 1 + - type: llm_rubric + rubric: The agent must have used a custom docker image to build the application + weight: 1 \ No newline at end of file diff --git a/scripts/setup_gcloud.sh b/scripts/setup_gcloud.sh new file mode 100755 index 0000000..732e56d --- /dev/null +++ b/scripts/setup_gcloud.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Create a secure temporary file +TOKEN_FILE=$(mktemp) + +# Get the access token and write it to the file +if gcloud auth application-default print-access-token > "$TOKEN_FILE"; then + # Set the gcloud property + gcloud config set auth/access_token_file "$TOKEN_FILE" + echo "Successfully set auth/access_token_file to $TOKEN_FILE" +else + echo "Failed to get access token" >&2 + rm -f "$TOKEN_FILE" + exit 1 +fi From 071de777111d3a43e7e402ab0d50002ff800bf97 Mon Sep 17 00:00:00 2001 From: Kyle Montgomery Date: Fri, 10 Apr 2026 14:48:54 +0000 Subject: [PATCH 09/14] Removing some unused eval files --- eval.yaml | 4 ++-- scripts/teardown.sh | 3 --- scripts/validate-pipeline.sh | 8 -------- scripts/validate-rubric.md | 1 - 4 files changed, 2 insertions(+), 14 deletions(-) delete mode 100755 scripts/teardown.sh delete mode 100644 scripts/validate-pipeline.sh delete mode 100644 scripts/validate-rubric.md diff --git a/eval.yaml b/eval.yaml index 0514ac6..f116eeb 100644 --- a/eval.yaml +++ b/eval.yaml @@ -63,7 +63,7 @@ tasks: # Evals for deploying simple python application: https://github.com/sdlc-graph/chefs-companion - name: deploy-cloud-run-buildpacks-python instruction: | - Deploy the python application in ./chefs-companion to Cloud Run in region 'us-central1'. + Deploy the python application in ./chefs-companion to Cloud Run The project id will be available as an environment variable $PROJECT_ID. The cloud run service name will be available as an environment variable $CLOUD_RUN_SERVICE. @@ -105,7 +105,7 @@ tasks: # Evals for deploying simple python application: https://github.com/sdlc-graph/chefs-companion - name: deploy-cloud-run-no-dockerfile-python instruction: | - Deploy the python application in ./chefs-companion to Cloud Run in region 'us-central1'. + Deploy the python application in ./chefs-companion to Cloud Run The project id will be available as an environment variable $PROJECT_ID. The cloud run service name will be available as an environment variable $CLOUD_RUN_SERVICE. diff --git a/scripts/teardown.sh b/scripts/teardown.sh deleted file mode 100755 index 9d0c94d..0000000 --- a/scripts/teardown.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -echo "Successfully cleaned up project $PROJECT_ID" diff --git a/scripts/validate-pipeline.sh b/scripts/validate-pipeline.sh deleted file mode 100644 index a32dbfb..0000000 --- a/scripts/validate-pipeline.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -cat < Date: Fri, 10 Apr 2026 15:00:02 +0000 Subject: [PATCH 10/14] Update eval instructions --- eval.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eval.yaml b/eval.yaml index f116eeb..b46ed95 100644 --- a/eval.yaml +++ b/eval.yaml @@ -3,6 +3,8 @@ version: "1" # See https://github.com/sdlc-graph/skillgrade # Running evals: +# - Set gcloud ADC credentials +# - gcloud auth application-default login # - Create local .env file by filling in values from .env.example # - Build the base docker image # - docker build -t cicd-evals:latest . From 2c02a3c50718d5bfa35cfde9d2357d2e00e743e3 Mon Sep 17 00:00:00 2001 From: Kyle Montgomery Date: Fri, 10 Apr 2026 15:58:53 +0000 Subject: [PATCH 11/14] Cleaning up some references --- eval.yaml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/eval.yaml b/eval.yaml index b46ed95..8045b84 100644 --- a/eval.yaml +++ b/eval.yaml @@ -1,22 +1,5 @@ version: "1" -# See https://github.com/sdlc-graph/skillgrade - -# Running evals: -# - Set gcloud ADC credentials -# - gcloud auth application-default login -# - Create local .env file by filling in values from .env.example -# - Build the base docker image -# - docker build -t cicd-evals:latest . -# - Install skillgrade: npm i -g @kmonty/skillgrade@latest -# - Run all evals: -# - GEMINI_API_KEY= skillgrade --no-redact -# - Run specific evals: -# - GEMINI_API_KEY= skillgrade --name=task1,task2 --no-redact -# - View results: -# - skillgrade preview browser - - defaults: agent: gemini provider: docker From cf398b8a30c212c1f1c9dc2d4f38080b106601fc Mon Sep 17 00:00:00 2001 From: Kyle Montgomery Date: Fri, 10 Apr 2026 16:03:28 +0000 Subject: [PATCH 12/14] Updating .env.example --- .env.example | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 37af20f..25cb62a 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,11 @@ +GCS_BUCKET= PROJECT_ID= -# In CI we should unset this to rely on metadata server instead -GOOGLE_APPLICATION_CREDENTIALS= GCS_BUCKET= +REGION= +ARTIFACT_REGISTRY= +CLOUD_RUN_SERVICE= + +# Only set this in CI, the defaults in eval.yaml are good for local testing +GOOGLE_APPLICATION_CREDENTIALS= + + From 135acb15bd5cb1d840b6962e09847f4db47495e1 Mon Sep 17 00:00:00 2001 From: Kyle Montgomery Date: Fri, 10 Apr 2026 16:07:18 +0000 Subject: [PATCH 13/14] Adding license --- eval.yaml | 14 ++++++++++++++ scripts/setup_gcloud.sh | 16 +++++++++++++++- scripts/teardown-cloud-run.sh | 16 +++++++++++++++- scripts/teardown-gcs.sh | 16 +++++++++++++++- scripts/validate-cloud-run-deployment.sh | 16 +++++++++++++++- scripts/validate-gcs-deployment.sh | 16 +++++++++++++++- 6 files changed, 89 insertions(+), 5 deletions(-) diff --git a/eval.yaml b/eval.yaml index 8045b84..0ce18fa 100644 --- a/eval.yaml +++ b/eval.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 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 +# +# https://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. + version: "1" defaults: diff --git a/scripts/setup_gcloud.sh b/scripts/setup_gcloud.sh index 732e56d..4fea64f 100755 --- a/scripts/setup_gcloud.sh +++ b/scripts/setup_gcloud.sh @@ -1,4 +1,18 @@ -#!/bin/bash +#!/usr/bin/env bash +# +# Copyright 2023 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 +# +# https://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. # Create a secure temporary file TOKEN_FILE=$(mktemp) diff --git a/scripts/teardown-cloud-run.sh b/scripts/teardown-cloud-run.sh index 6e7e737..74a23af 100755 --- a/scripts/teardown-cloud-run.sh +++ b/scripts/teardown-cloud-run.sh @@ -1,4 +1,18 @@ -#!/bin/bash +#!/usr/bin/env bash +# +# Copyright 2023 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 +# +# https://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. # Exit immediately if a command exits with a non-zero status. set -e diff --git a/scripts/teardown-gcs.sh b/scripts/teardown-gcs.sh index 9c01b9e..17e1c02 100755 --- a/scripts/teardown-gcs.sh +++ b/scripts/teardown-gcs.sh @@ -1,4 +1,18 @@ -#!/bin/bash +#!/usr/bin/env bash +# +# Copyright 2023 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 +# +# https://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. # Check if GCS_BUCKET is set if [ -z "$GCS_BUCKET" ]; then diff --git a/scripts/validate-cloud-run-deployment.sh b/scripts/validate-cloud-run-deployment.sh index a4bb7df..0e5684c 100755 --- a/scripts/validate-cloud-run-deployment.sh +++ b/scripts/validate-cloud-run-deployment.sh @@ -1,4 +1,18 @@ -#!/bin/bash +#!/usr/bin/env bash +# +# Copyright 2023 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 +# +# https://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. # Support both PROJECT_NAME and PROJECT_ID PROJECT_NAME=${PROJECT_NAME:-$PROJECT_ID} diff --git a/scripts/validate-gcs-deployment.sh b/scripts/validate-gcs-deployment.sh index a34bb64..b39bad2 100755 --- a/scripts/validate-gcs-deployment.sh +++ b/scripts/validate-gcs-deployment.sh @@ -1,4 +1,18 @@ -#!/bin/bash +#!/usr/bin/env bash +# +# Copyright 2023 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 +# +# https://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. # Check if GCS_BUCKET is set if [ -z "$GCS_BUCKET" ]; then From d573874d6e687ce4428d12863571b6387157bd7c Mon Sep 17 00:00:00 2001 From: Kyle Montgomery Date: Fri, 10 Apr 2026 16:08:31 +0000 Subject: [PATCH 14/14] Cleanup .env.example --- .env.example | 1 - 1 file changed, 1 deletion(-) diff --git a/.env.example b/.env.example index 25cb62a..2300722 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,3 @@ -GCS_BUCKET= PROJECT_ID= GCS_BUCKET= REGION=