secrets: inheritis configured in the caller job, not in the called workflow.permissionsmust also be set deliberately in the caller job when org defaults are restrictive.- A reusable workflow cannot elevate beyond caller token permissions.
uses: ./.github/actions/...resolves in the caller repository when called cross-repo.- For reusable workflows intended for other repos, use fully-qualified references:
owner/repo/path@ref
- Direct
if: secrets.X != ''caused parse errors in called workflows. - Safe pattern:
- Read secrets in a shell step
env - Validate pair completeness
- Write
enabled=true/falseto$GITHUB_OUTPUT - Gate later steps with
if: steps.<id>.outputs.enabled == 'true'
- Read secrets in a shell step
- Exclude pathspecs like
:!pnpm-lock.yamlrequire--before pathspec arguments. - Inputs containing literal shell quote characters can become invalid pathspecs.
- Normalize/strip quote characters before building arrays.
- Client secret alone is not enough.
- Required for app-token auth:
- App ID / client ID
- App private key (PEM)
- For this setup, workflows use:
JULES_PR_CLIENT_IDJULES_PR_PRIVATE_KEY
- For changelog PRs with App auth, derive bot identity from app slug + bot user id:
<app-slug>[bot] <id+app-slug[bot]@users.noreply.github.com>
- Pass identity to both
authorandcommitter.
- Explicitly define workflow/job
permissionsinstead of relying on org/repo defaults. - Current hardening:
- Reusable Rust CI:
contents: read - Reusable Rust Release: default
contents: read, withcreate-releasejob overriding tocontents: write
- Reusable Rust CI:
- Callers pinned to older SHAs keep old behavior/bugs.
- After fixes land, callers should update reference (
@mainor a new pinned SHA/tag).