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
4 changes: 4 additions & 0 deletions .github/workflows/deploy-runner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ on:
branches: [main]
paths:
- "cloud-run/**"
# Deploys can fail for reasons outside the code (a missing IAM grant, a Cloud
# Build outage). Without this the only way to retry was to push a no-op
# commit, which is worse than useless on the branch that deploys production.
workflow_dispatch:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 Manual retry can deploy unmerged runner code

When an operator selects another branch, workflow_dispatch deploys that branch's runner to production. Checkout uses the selected ref, so the retry can replace the main revision with unmerged code.

Learn more

A manual workflow run lets the operator choose a branch. Actions checkout uses that selected ref by default, and deploy script sends the checked-out cloud-run/ffai-runner source to the production service. The new trigger has no branch restriction, so choosing a feature branch deploys its unmerged runner instead of retrying the production revision.

Example: An operator selects fix/runner-experiment in Run workflow after a failed main deploy. The workflow checks out that branch and publishes its runner, even though main still contains the production-approved source.

Recommended fix: Restrict this job to refs/heads/main, or explicitly check out main for manual retries. If manual runs from other branches are needed, route them to a separate non-production target.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.


# The deploy script needs `gcloud` (auth + setup-gcloud below). No write access
# to this repository itself is required.
Expand Down
15 changes: 10 additions & 5 deletions DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,16 @@ changes will deploy nothing:
| `roles/iam.serviceAccountUser` | act as the runtime service account |
| `roles/cloudbuild.builds.editor` | run the build |
| `roles/artifactregistry.writer` | push the built image (else `artifactregistry.repositories.get` is denied) |
| `roles/storage.objectAdmin` | read/write the source bucket `run-sources-<project>-<region>` (else `storage.buckets.get` is denied) |

Scope the last two to the repository and bucket if you prefer, but a partial
set fails at deploy time with a message naming only the next missing
permission — which is how this list was corrected twice.
| `roles/storage.admin` | the source bucket: read its metadata (`storage.buckets.get`, `storage.buckets.list`) and write the objects in it |

`roles/storage.admin` is the one to grant, and the narrower storage roles do
**not** compose into a substitute. Measured against the live role definitions:
`storage.objectAdmin` has 32 permissions and not one is `storage.buckets.*`;
`storage.legacyBucketReader` supplies `storage.buckets.get` but not
`storage.buckets.list`. A source deploy needs `buckets.get`, `buckets.list`
and `objects.create`, and only `storage.admin` supplies all three — so the
failures arrive one permission at a time and each looks like the last one
being wrong.
2. In **Settings → Secrets and variables → Actions**, create a repository secret
named `CCC_FFAI_RUNNER_SA_KEY_JSON` whose value is the key's full JSON
(including the surrounding `{ }`).
Expand Down
Loading