Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/app.template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
service: ${SERVICE_NAME}
runtime: python313
entrypoint: gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app
instance_class: F4
service_account: "${CLOUD_SQL_USER}.gserviceaccount.com"
handlers:
- url: /.*
secure: always
script: auto
env_variables:
MODE: "production"
ENVIRONMENT: "${ENVIRONMENT}"
DB_DRIVER: "cloudsql"
CLOUD_SQL_INSTANCE_NAME: "${CLOUD_SQL_INSTANCE_NAME}"
CLOUD_SQL_DATABASE: "${CLOUD_SQL_DATABASE}"
CLOUD_SQL_USER: "${CLOUD_SQL_USER}"
PYGEOAPI_POSTGRES_DB: "${PYGEOAPI_POSTGRES_DB}"
PYGEOAPI_POSTGRES_USER: "${PYGEOAPI_POSTGRES_USER}"
PYGEOAPI_POSTGRES_HOST: "${PYGEOAPI_POSTGRES_HOST}"
PYGEOAPI_POSTGRES_PORT: "${PYGEOAPI_POSTGRES_PORT}"
PYGEOAPI_POSTGRES_PASSWORD: "${PYGEOAPI_POSTGRES_PASSWORD}"
PYGEOAPI_SERVER_URL: "${PYGEOAPI_SERVER_URL}"
CLOUD_SQL_IAM_AUTH: "${CLOUD_SQL_IAM_AUTH}"
GCS_SERVICE_ACCOUNT_KEY: "${GCS_SERVICE_ACCOUNT_KEY}"
GCS_BUCKET_NAME: "${GCS_BUCKET_NAME}"
AUTHENTIK_URL: "${AUTHENTIK_URL}"
AUTHENTIK_CLIENT_ID: "${AUTHENTIK_CLIENT_ID}"
AUTHENTIK_AUTHORIZE_URL: "${AUTHENTIK_AUTHORIZE_URL}"
AUTHENTIK_TOKEN_URL: "${AUTHENTIK_TOKEN_URL}"
SESSION_SECRET_KEY: "${SESSION_SECRET_KEY}"
APITALLY_CLIENT_ID: "${APITALLY_CLIENT_ID}"
64 changes: 30 additions & 34 deletions .github/workflows/CD_production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,41 +47,37 @@ jobs:
run: |
uv run alembic upgrade head

- name: Create app.yaml
- name: Ensure envsubst is available
run: |
cat <<EOF > app.yaml
service: ocotillo-api
runtime: python313
entrypoint: gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app
instance_class: F4
service_account: "${{ secrets.CLOUD_SQL_USER }}.gserviceaccount.com"
handlers:
- url: /.*
secure: always
script: auto
env_variables:
MODE: "production"
ENVIRONMENT: "production"
DB_DRIVER: "cloudsql"
CLOUD_SQL_INSTANCE_NAME: "${{ secrets.CLOUD_SQL_INSTANCE_NAME }}"
CLOUD_SQL_DATABASE: "${{ vars.CLOUD_SQL_DATABASE }}"
CLOUD_SQL_USER: "${{ secrets.CLOUD_SQL_USER }}"
PYGEOAPI_POSTGRES_DB: "${{ vars.CLOUD_SQL_DATABASE }}"
PYGEOAPI_POSTGRES_USER: "${{ secrets.PYGEOAPI_POSTGRES_USER }}"
PYGEOAPI_POSTGRES_HOST: "${{ vars.PYGEOAPI_POSTGRES_HOST || '127.0.0.1' }}"
PYGEOAPI_POSTGRES_PORT: "${{ vars.PYGEOAPI_POSTGRES_PORT || '5432' }}"
PYGEOAPI_POSTGRES_PASSWORD: "${{ secrets.PYGEOAPI_POSTGRES_PASSWORD }}"
PYGEOAPI_SERVER_URL: "${{ vars.PYGEOAPI_SERVER_URL }}"
CLOUD_SQL_IAM_AUTH: true
GCS_SERVICE_ACCOUNT_KEY: "${{ secrets.GCS_SERVICE_ACCOUNT_KEY }}"
GCS_BUCKET_NAME: "${{ vars.GCS_BUCKET_NAME }}"
AUTHENTIK_URL: "${{ vars.AUTHENTIK_URL }}"
AUTHENTIK_CLIENT_ID: "${{ vars.AUTHENTIK_CLIENT_ID }}"
AUTHENTIK_AUTHORIZE_URL: "${{ vars.AUTHENTIK_AUTHORIZE_URL }}"
AUTHENTIK_TOKEN_URL: "${{ vars.AUTHENTIK_TOKEN_URL }}"
SESSION_SECRET_KEY: "${{ secrets.SESSION_SECRET_KEY }}"
APITALLY_CLIENT_ID: "${{ vars.APITALLY_CLIENT_ID }}"
EOF
if ! command -v envsubst >/dev/null 2>&1; then
sudo apt-get update
sudo apt-get install -y gettext-base
fi

- name: Render app.yaml
env:
SERVICE_NAME: "ocotillo-api"
ENVIRONMENT: "production"
CLOUD_SQL_INSTANCE_NAME: "${{ secrets.CLOUD_SQL_INSTANCE_NAME }}"
CLOUD_SQL_DATABASE: "${{ vars.CLOUD_SQL_DATABASE }}"
CLOUD_SQL_USER: "${{ secrets.CLOUD_SQL_USER }}"
PYGEOAPI_POSTGRES_DB: "${{ vars.CLOUD_SQL_DATABASE }}"
PYGEOAPI_POSTGRES_USER: "${{ secrets.PYGEOAPI_POSTGRES_USER }}"
PYGEOAPI_POSTGRES_HOST: "${{ vars.PYGEOAPI_POSTGRES_HOST || '127.0.0.1' }}"
PYGEOAPI_POSTGRES_PORT: "${{ vars.PYGEOAPI_POSTGRES_PORT || '5432' }}"
Comment on lines +66 to +67
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub Actions does not support the || operator for providing default values in the env context. The expression ${{ vars.PYGEOAPI_POSTGRES_PORT || '5432' }} will always evaluate to the first value (even if empty) rather than falling back to the default. Consider using a separate step to set defaults, or use a ternary expression like ${{ vars.PYGEOAPI_POSTGRES_PORT != '' && vars.PYGEOAPI_POSTGRES_PORT || '5432' }}.

Suggested change
PYGEOAPI_POSTGRES_HOST: "${{ vars.PYGEOAPI_POSTGRES_HOST || '127.0.0.1' }}"
PYGEOAPI_POSTGRES_PORT: "${{ vars.PYGEOAPI_POSTGRES_PORT || '5432' }}"
PYGEOAPI_POSTGRES_HOST: "${{ vars.PYGEOAPI_POSTGRES_HOST != '' && vars.PYGEOAPI_POSTGRES_HOST || '127.0.0.1' }}"
PYGEOAPI_POSTGRES_PORT: "${{ vars.PYGEOAPI_POSTGRES_PORT != '' && vars.PYGEOAPI_POSTGRES_PORT || '5432' }}"

Copilot uses AI. Check for mistakes.
PYGEOAPI_POSTGRES_PASSWORD: "${{ secrets.PYGEOAPI_POSTGRES_PASSWORD }}"
PYGEOAPI_SERVER_URL: "${{ vars.PYGEOAPI_SERVER_URL }}"
CLOUD_SQL_IAM_AUTH: "true"
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CLOUD_SQL_IAM_AUTH value has been changed from a boolean true to a string "true". While YAML will treat both as truthy values, this may cause issues if the application code expects a boolean type. Verify that the application correctly handles string values for this environment variable, or consider using true without quotes to maintain consistency with the previous implementation.

Suggested change
CLOUD_SQL_IAM_AUTH: "true"
CLOUD_SQL_IAM_AUTH: true

Copilot uses AI. Check for mistakes.
GCS_SERVICE_ACCOUNT_KEY: "${{ secrets.GCS_SERVICE_ACCOUNT_KEY }}"
GCS_BUCKET_NAME: "${{ vars.GCS_BUCKET_NAME }}"
AUTHENTIK_URL: "${{ vars.AUTHENTIK_URL }}"
AUTHENTIK_CLIENT_ID: "${{ vars.AUTHENTIK_CLIENT_ID }}"
AUTHENTIK_AUTHORIZE_URL: "${{ vars.AUTHENTIK_AUTHORIZE_URL }}"
AUTHENTIK_TOKEN_URL: "${{ vars.AUTHENTIK_TOKEN_URL }}"
SESSION_SECRET_KEY: "${{ secrets.SESSION_SECRET_KEY }}"
APITALLY_CLIENT_ID: "${{ vars.APITALLY_CLIENT_ID }}"
run: |
envsubst < .github/app.template.yaml > app.yaml

- name: Deploy to Google Cloud
run: |
Expand Down
65 changes: 30 additions & 35 deletions .github/workflows/CD_staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,42 +47,37 @@ jobs:
run: |
uv run alembic upgrade head

# Uses Google Cloud Secret Manager to store secret credentials
- name: Create app.yaml
- name: Ensure envsubst is available
run: |
cat <<EOF > app.yaml
service: ocotillo-api-staging
runtime: python313
entrypoint: gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app
service_account: "${{ secrets.CLOUD_SQL_USER }}.gserviceaccount.com"
instance_class: F4
handlers:
- url: /.*
secure: always
script: auto
env_variables:
MODE: "production"
ENVIRONMENT: "staging"
DB_DRIVER: "cloudsql"
CLOUD_SQL_INSTANCE_NAME: "${{ secrets.CLOUD_SQL_INSTANCE_NAME }}"
CLOUD_SQL_DATABASE: "${{ vars.CLOUD_SQL_DATABASE }}"
CLOUD_SQL_USER: "${{ secrets.CLOUD_SQL_USER }}"
PYGEOAPI_POSTGRES_DB: "${{ vars.CLOUD_SQL_DATABASE }}"
PYGEOAPI_POSTGRES_USER: "${{ secrets.PYGEOAPI_POSTGRES_USER }}"
PYGEOAPI_POSTGRES_HOST: "${{ vars.PYGEOAPI_POSTGRES_HOST || '127.0.0.1' }}"
PYGEOAPI_POSTGRES_PORT: "${{ vars.PYGEOAPI_POSTGRES_PORT || '5432' }}"
PYGEOAPI_POSTGRES_PASSWORD: "${{ secrets.PYGEOAPI_POSTGRES_PASSWORD }}"
PYGEOAPI_SERVER_URL: "${{ vars.PYGEOAPI_SERVER_URL }}"
CLOUD_SQL_IAM_AUTH: true
GCS_SERVICE_ACCOUNT_KEY: "${{ secrets.GCS_SERVICE_ACCOUNT_KEY }}"
GCS_BUCKET_NAME: "${{ vars.GCS_BUCKET_NAME }}"
AUTHENTIK_URL: "${{ vars.AUTHENTIK_URL }}"
AUTHENTIK_CLIENT_ID: "${{ vars.AUTHENTIK_CLIENT_ID }}"
AUTHENTIK_AUTHORIZE_URL: "${{ vars.AUTHENTIK_AUTHORIZE_URL }}"
AUTHENTIK_TOKEN_URL: "${{ vars.AUTHENTIK_TOKEN_URL }}"
SESSION_SECRET_KEY: "${{ secrets.SESSION_SECRET_KEY }}"
APITALLY_CLIENT_ID: "${{ vars.APITALLY_CLIENT_ID }}"
EOF
if ! command -v envsubst >/dev/null 2>&1; then
sudo apt-get update
sudo apt-get install -y gettext-base
fi

- name: Render app.yaml
env:
SERVICE_NAME: "ocotillo-api-staging"
ENVIRONMENT: "staging"
CLOUD_SQL_INSTANCE_NAME: "${{ secrets.CLOUD_SQL_INSTANCE_NAME }}"
CLOUD_SQL_DATABASE: "${{ vars.CLOUD_SQL_DATABASE }}"
CLOUD_SQL_USER: "${{ secrets.CLOUD_SQL_USER }}"
PYGEOAPI_POSTGRES_DB: "${{ vars.CLOUD_SQL_DATABASE }}"
PYGEOAPI_POSTGRES_USER: "${{ secrets.PYGEOAPI_POSTGRES_USER }}"
PYGEOAPI_POSTGRES_HOST: "${{ vars.PYGEOAPI_POSTGRES_HOST || '127.0.0.1' }}"
PYGEOAPI_POSTGRES_PORT: "${{ vars.PYGEOAPI_POSTGRES_PORT || '5432' }}"
Comment on lines +66 to +67
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub Actions does not support the || operator for providing default values in the env context. The expression ${{ vars.PYGEOAPI_POSTGRES_HOST || '127.0.0.1' }} will always evaluate to the first value (even if empty) rather than falling back to the default. Consider using a separate step to set defaults, or use a ternary expression like ${{ vars.PYGEOAPI_POSTGRES_HOST != '' && vars.PYGEOAPI_POSTGRES_HOST || '127.0.0.1' }}.

Suggested change
PYGEOAPI_POSTGRES_HOST: "${{ vars.PYGEOAPI_POSTGRES_HOST || '127.0.0.1' }}"
PYGEOAPI_POSTGRES_PORT: "${{ vars.PYGEOAPI_POSTGRES_PORT || '5432' }}"
PYGEOAPI_POSTGRES_HOST: "${{ vars.PYGEOAPI_POSTGRES_HOST != '' && vars.PYGEOAPI_POSTGRES_HOST || '127.0.0.1' }}"
PYGEOAPI_POSTGRES_PORT: "${{ vars.PYGEOAPI_POSTGRES_PORT != '' && vars.PYGEOAPI_POSTGRES_PORT || '5432' }}"

Copilot uses AI. Check for mistakes.
PYGEOAPI_POSTGRES_PASSWORD: "${{ secrets.PYGEOAPI_POSTGRES_PASSWORD }}"
PYGEOAPI_SERVER_URL: "${{ vars.PYGEOAPI_SERVER_URL }}"
CLOUD_SQL_IAM_AUTH: "true"
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CLOUD_SQL_IAM_AUTH value has been changed from a boolean true to a string "true". While YAML will treat both as truthy values, this may cause issues if the application code expects a boolean type. Verify that the application correctly handles string values for this environment variable, or consider using true without quotes to maintain consistency with the previous implementation.

Copilot uses AI. Check for mistakes.
GCS_SERVICE_ACCOUNT_KEY: "${{ secrets.GCS_SERVICE_ACCOUNT_KEY }}"
GCS_BUCKET_NAME: "${{ vars.GCS_BUCKET_NAME }}"
AUTHENTIK_URL: "${{ vars.AUTHENTIK_URL }}"
AUTHENTIK_CLIENT_ID: "${{ vars.AUTHENTIK_CLIENT_ID }}"
AUTHENTIK_AUTHORIZE_URL: "${{ vars.AUTHENTIK_AUTHORIZE_URL }}"
AUTHENTIK_TOKEN_URL: "${{ vars.AUTHENTIK_TOKEN_URL }}"
SESSION_SECRET_KEY: "${{ secrets.SESSION_SECRET_KEY }}"
APITALLY_CLIENT_ID: "${{ vars.APITALLY_CLIENT_ID }}"
run: |
envsubst < .github/app.template.yaml > app.yaml

- name: Deploy to Google Cloud
run: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,4 @@ cli/logs
.pygeoapi/
# deployment files
app.yaml
docs/