Add fork-safe PR build workflow#442
Merged
Merged
Conversation
Move all ${{ }} expressions out of run: blocks into env:
blocks to prevent script injection from runtime values
(matrix outputs, secrets). This makes the "no expressions
in run blocks" rule enforceable by zizmor without
per-expression exceptions.
- bakery-build-native.yml: matrix, build-test (filter,
build, test), merge (filter, merge/push), readme steps
- bakery-build.yml: matrix, build (filter, build, test,
push), readme steps
- Convert conditional push flag to shell logic
- Quote all shell variable references
Move all ${{ }} expressions out of run: blocks into env:
blocks in clean.yml, product-release.yml, hadolint.yml,
and ci.yml (release job).
- clean.yml: Convert conditional flags (dry-run, untagged,
older-than) from expression ternaries to shell logic
- product-release.yml: Move inputs.version and step
outputs to env vars
- hadolint.yml: Move inputs.context to env var
- ci.yml: Move github.ref_name to env var in release step
Declare least-privilege permissions on all shared
reusable workflows. Each workflow gets permissions: {}
at the top level to drop all default permissions, then
per-job permissions grant only what is needed.
- bakery-build-native.yml: matrix {}, build-test and
merge {contents: read, packages: write}, readme
{contents: read}
- bakery-build.yml: matrix {}, build {contents: read,
packages: write}, readme {contents: read}
- clean.yml: both jobs {contents: read, packages: write}
- hadolint.yml: {contents: read}
- product-release.yml: top-level {} (job-level already
existed)
Declare least-privilege permissions for the CI and
issue automation workflows.
- ci.yml: top-level {}, ci meta-job {}, test
{contents: read}, release {contents: write}. Bakery
and clean jobs already had permissions declared.
- issues.yml: top-level {} and job-level {} since the
job uses a GitHub App token, not GITHUB_TOKEN
Matrix jobs in bakery-build-native.yml and bakery-build.yml had
permissions: {} but use actions/checkout, which requires
contents: read on private repos.
Build and merge jobs use aws-actions/configure-aws-credentials
with OIDC role assumption, which requires id-token: write. Add
the permission to build-test and merge in the native workflow
and build in the QEMU workflow.
The ci.yml test job uses publish-unit-test-result-action which
needs checks: write to post results.
Dependabot and fork PRs get a restricted GITHUB_TOKEN without checks:write permission. The publish-unit-test- result-action fails with 403 in that context. Skip it rather than switching to pull_request_target, which is unsafe for code checkout workflows. Tests still run and report pass/fail via job status.
Resolve conflict in hadolint.yml where main added the base workflow and this branch added the security policy comment, permissions, and env var pattern.
Fork PRs have the same restricted GITHUB_TOKEN as Dependabot PRs — checks:write is unavailable. Check both github.actor and the fork flag.
Reusable workflow (workflow_call) top-level permissions
act as a ceiling — the caller can never grant more than
what the reusable workflow declares. With permissions: {},
the caller's job-level permissions (contents:read,
packages:write, etc.) are blocked entirely, causing a
startup_failure.
Job-level permissions within the reusable workflow are
kept — they constrain what each job uses without blocking
what the caller grants.
Top-level permissions: {} on a workflow that calls
reusable workflows may constrain the caller-to-callee
permission grant, causing startup_failure. Remove it
and rely on per-job permissions declarations instead.
Job-level permissions in a reusable workflow cannot exceed what the caller grants. The caller (ci.yml) grants contents:read + packages:write but not id-token:write, causing startup_failure when the callee's job declares it. The id-token:write permission for AWS OIDC must be granted by the caller, not declared inside the reusable workflow.
The publish-unit-test-result-action posts a comment on the PR which requires pull-requests:write in addition to checks:write.
New bakery-build-pr.yml shared workflow for PR builds that works safely with fork PRs. Key differences from the native build workflow: - Detects fork PRs and conditionally skips GHCR login/cache - No push, no merge, no readme jobs - Skips arm64 builds for fork PRs (paid runners unavailable) - No secrets section — uses only inherited GITHUB_TOKEN - All expressions in env: blocks, never in run: blocks
Add bakery-pr job to ci.yml that exercises the new fork-safe PR workflow on pull_request events. Added to allowed-skips since it only runs on PRs (not push/merge_group).
The head_ref pattern used by other CI jobs breaks on fork PRs because the fork's branch doesn't exist in the base repo. The PR build job uses the default "main" version instead, which always resolves.
Top-level permissions on workflow_call workflows act as a ceiling that blocks caller-granted permissions, causing startup_failure. Use per-job permissions only.
77c622b to
5a07624
Compare
2 tasks
bschwedler
added a commit
that referenced
this pull request
Apr 13, 2026
bakery-build-pr.yml was added in #442 but missed the SHA-pinning pass in #443. Pin all third-party actions to full-length commit SHAs matching bakery-build-native.yml, and add timeout-minutes to all three jobs (detect: 5m, matrix: 10m, build-test: 120m). - Upgrade oras-project/setup-oras from v1 to v2.0.0 for consistency with the native build workflow - First-party composite actions (setup-bakery, setup-goss) intentionally kept at @main per zizmor ref-pin policy
bschwedler
added a commit
that referenced
this pull request
Apr 13, 2026
Now that bakery-build-pr.yml exists on main (merged in #442), the relative ref resolves correctly. This matches the pattern used by bakery-build.yml and bakery-build-native.yml, and lets PRs that modify bakery-build-pr.yml test their own changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
bakery-build-pr.ymlreusable workflow for pull request buildsgithub.event.pull_request.head.repo.forksecrets:section — only inheritedGITHUB_TOKENci.ymlwith abakery-prtest jobProduct repos will adopt this in follow-up PRs by creating
pr.ymland removingpull_requestfrom existing workflows.Depends on #440 (script injection + permissions fixes should merge first).
Addresses the core of rstudio/platform-team#435.
Test plan
bakery-prjob runs on this PRdetectjob outputsis-fork: falsefor internal PRs