When trying to deploy to App Engine from GitHub Actions, the process fails with the error:
Error Response: [13] An internal error occurred.
However, running the equivalent commands from my local environment succeeds. Is there any recommended way to investigate this issue further or any clues that could help identify the root cause?
For reference, the service account used with google-github-actions/auth@v2
has the actAs permission for the service account used during deployment.
Full logs::
Run google-github-actions/deploy-appengine@v2
with:
project_id: ***
promote: true
env:
pythonLocation: /opt/hostedtoolcache/Python/3.10.16/x64
PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.10.16/x64/lib/pkgconfig
Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.10.16/x64
Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.10.16/x64
Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.10.16/x64
LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.10.16/x64/lib
CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE: /home/runner/work/foo/foo/gha-creds-6fcf9b1857096975.json
GOOGLE_APPLICATION_CREDENTIALS: /home/runner/work/foo/foo/gha-creds-6fcf9b1857096975.json
GOOGLE_GHA_CREDS_PATH: /home/runner/work/foo/foo/gha-creds-6fcf9b1857096975.json
CLOUDSDK_CORE_PROJECT: ***
CLOUDSDK_PROJECT: ***
GCLOUD_PROJECT: ***
GCP_PROJECT: ***
GOOGLE_CLOUD_PROJECT: ***
/usr/bin/tar xz --warning=no-unknown-keyword --overwrite -C /home/runner/work/_temp/d58fdd10-60bc-4546-9e1d-35844ca90d5d -f /home/runner/work/_temp/92b21d4b-b144-4f74-99f3-5120413e830a
Successfully authenticated
Running: gcloud app deploy --format json app.yaml --project *** --promote
Error: google-github-actions/deploy-appengine failed with: failed to execute gcloud command `gcloud app deploy --format json app.yaml --project *** --promote`: Services to deploy:
descriptor: [/home/runner/work/foo/foo/app.yaml]
source: [/home/runner/work/foo/foo]
target project: [***]
target service: [foo]
target version: [20250402t015844]
target url: [https://foo-dot-***.uc.r.appspot.com]
target service account: [***@appspot.gserviceaccount.com]
Beginning deployment of service [foo]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 0 files to Google Cloud Storage ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [foo]...
..................................failed.
ERROR: (gcloud.app.deploy) Error Response: [13] An internal error occurred.
Yaml File::
name: deploy
on:
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Setup python
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install poetry
run: |
pip install poetry
- name: Install dependencies
run: |
poetry self add poetry-plugin-export
poetry export --without-hashes -f requirements.txt --output requirements.txt
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
service_account: ${{ secrets.GCP_OIDC_SERVICE_ACCOUNT }}
workload_identity_provider: ${{ secrets.GCP_OIDC_PROVIDER }}
- name: Generate app.env.yml to include app.yaml
run: |
cat <<EOF > ./app.env.yml
env_variables:
FOO: $(gcloud secrets versions access latest --secret="FOO")
EOF
- name: Deploy to Google Cloud
uses: 'google-github-actions/deploy-appengine@v2'
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
In the end, I found the answer in the README of the official GitHub Action for deploying to App Engine.
According to the Authorization section of the README, the service account connecting via OIDC needs the following roles:
App Engine Admin (roles/appengine.appAdmin): Required to manage App Engine resources
Storage Admin (roles/storage.admin): Required to upload files to Cloud Storage
Cloud Build Editor (roles/cloudbuild.builds.editor): Required to build the service
Artifact Registry Reader (roles/artifactregistry.reader): Required to retrieve artifacts for CI/CD pipelines
Service Account User (roles/iam.serviceAccountUser): Required to deploy the service using a runtime service account (by default, this is PROJECT_ID@appspot.gserviceaccount.com
(Optional) Cloud Scheduler Admin (roles/cloudscheduler.admin): Required if you need to schedule tasks
This information was not mentioned anywhere in the error messages shown by gcloud app deploy
—at least not as far as I could tell.
The biggest trap was the missing roles/iam.serviceAccountUser permission. Unlike the other roles such as App Engine Admin or Storage Admin, there wasn’t even an error message indicating it was missing, which made debugging especially difficult.
Once I granted all of the above roles, the deployment finally worked as expected.