Repository navigation
Introduce a "PR mode" for attestations #3265
Description
Context / problem
When an attestation runs as part of a pull request / merge request, Chainloop today treats it the same as a build on main/a release. That causes two side-effects we don't want for PR builds:
- Latest promotion — PR builds get promoted to the project's "latest" version. The current workaround is manually passing
--mark-latest=false, but that flag was really meant to express "this is a PR build". We're overloading a low-level flag to express a higher-level concept. - Findings processing — policy violations from a PR build get processed (and later re-processed) as if they were findings from a real merge/release build. We want PR-originated attestations to be tagged so downstream consumers can choose not to (re)process them.
The underlying insight: the real concept we want is "PR mode", and both behaviors above should flow from that single signal rather than being manually wired via --mark-latest.
Decision (simplified)
After discussion, we're simplifying the original proposal. Instead of adding a new field on the WorkflowRun ent schema or tagging the policy evaluation object, we'll set a top-level annotation on the attestation. This keeps the change minimal and decouples the PR signal from the policy evaluation pipeline.
Well-known annotation key: chainloop.dev/is-pull-request with value "true".
This leverages the existing annotations map on the Attestation proto (crafting_state.proto), which already flows through the rendering pipeline — no proto schema changes, no DB migration, no codegen churn.
Detection — auto-detect + explicit override
- Auto-detect from the CI runner environment (already implemented in
DetectPRContext/prmetadata.go):- GitHub Actions:
GITHUB_EVENT_NAME=pull_request(orpull_request_target). - GitLab:
CI_PIPELINE_SOURCE=merge_request_event/CI_MERGE_REQUEST_IID. - Dagger: delegates to the parent CI env vars.
- GitHub Actions:
- Explicit
--pr/--pr=falseflag onchainloop attestation initoverrides auto-detection (zero-config in CI, escapable for edge cases / self-hosted / generic runner).
Behavior when in PR mode (by default)
- Skip latest promotion — default to
mark-latest=false. An explicitly-passed--mark-latest=truestill wins (respect explicit user intent). This replaces the manual--mark-latest=falseworkaround. - Set the
chainloop.dev/is-pull-request=trueannotation on the attestation so downstream consumers (e.g. findings processing) can detect PR-originated attestations and skip (re)processing.
Scope split
- OSS (this issue): capture & propagate the PR signal as a top-level annotation on the attestation; wire
--prflag andmark-latestdefault behavior. - SaaS (downstream): findings processing/reprocessing reads the annotation and decides whether to process. Not in scope for this issue.
Relevant code pointers
- PR detection (existing):
pkg/attestation/crafter/prmetadata.go(DetectPRContext),pkg/attestation/crafter/collector_prmetadata.go. - Runner env vars:
pkg/attestation/crafter/runners/githubaction.go,gitlabpipeline.go,daggerpipeline.go. - CLI flags:
app/cli/cmd/attestation_init.go(--mark-latest). - Attestation proto (annotations map):
pkg/attestation/crafter/api/attestation/v1/crafting_state.proto(Attestation.annotations, field 5). - Crafter init (where annotation would be set):
pkg/attestation/crafter/crafter.go(initialCraftingState). - Action layer:
app/cli/pkg/action/attestation_init.go.
🤖 Posted by Maximus bot (Claude Code) on behalf of @migmartri
Activity
migmartri commentedon Jul 15, 2026
Reopening this because the "skip latest promotion" part of PR mode was causing unwanted side-effects. In #3289 we've decoupled PR mode from latest promotion — PR mode now only sets the
chainloop.dev/is-pull-requestannotation, and--mark-latestremains the explicit control for promotion.cc @jiparis @javirln — let's review the approach for how (and whether) PR mode should influence latest promotion before wiring it back in.
🤖 Posted by Maximus bot (Claude Code) on behalf of @migmartri
jiparis commentedon Jul 15, 2026
I think it shouldn't influence latest promotion at all. Here we want to avoid PR evaluations from being ingested by findings processing, right? I don't think latest matters here, but in general, you'd want to use
--latest-versionfor PRs, so that they are attached to whichever the latest version is currently, without creating nor promoting any new version.github-actions commentedon Sep 14, 2026
This issue is stale because it has been open for 60 days with no activity. It will be closed in 7 days if no further activity occurs.
github-actions commentedon Sep 21, 2026
This issue was closed because it has been inactive for 7 days since being marked as stale. Feel free to reopen if it is still relevant.