Skip to content

Conversation

@javirln
Copy link
Member

@javirln javirln commented Jan 8, 2026

Problem

When running attestation init --remote-state in Dagger with PR context, the automatic PR metadata collection was failing with a digest mismatch error:

  failed to auto-collect PR/MR metadata error="failed to add PR/MR metadata material:
  failed to persist crafting state: failed to save state: rpc error: code = Aborted
  desc = saving attestation: failed to save attestation state: the provided base digest
  doesn't match the stored state"

This only affected remote attestations, not local filesystem-based ones.

Root Cause

Remote attestations use optimistic concurrency control with digest checksums. During attestation init:

  1. ResolveEnvVars() modifies and saves state → server calculates new digest
  2. Client's in-memory digest becomes stale
  3. AutoCollectPRMetadata() attempts to save with stale digest → conflict

This issue didn't affect attestation add or attestation push because those commands reload state before modifying it.

Solution

Added state reload at the beginning of AutoCollectPRMetadata() to ensure the digest checksum is current before making modifications

Testing

app/cli/chainloop attestation init --workflow "$WORKFLOW_NAME" --project "$PROJECT_NAME" --remote-state -o json
WRN API contacted in insecure mode
INF detected PR/MR context number=12 platform=github
INF successfully collected and attested PR/MR metadata
INF Attestation initialized! now you can check its status or add materials to it
{
   "attestationID": "6dcfb573-d32e-4fc6-8680-bf04e1182199",
   "initializedAt": "2026-01-08T13:26:58.291366Z",
   "workflowMeta": {
      "WorkflowID": "13568a0f-7232-48bf-8130-300e00357eee",
      "Name": "pr-validation",
      "Team": "",
      "Project": "core",
      "ContractRevision": "1",
      "ContractName": "core-pr-validation",
      "Organization": "testing",
      "ProjectVersion": {
         "id": "",
         "version": "v1.68.0+next",
         "prerelease": true,
         "markAsRelease": false
      }
   },
   "materials": [
      {
         "name": "pr-metadata",
         "value": "pr-metadata-3862956156.json",
         "hash": "sha256:52e97fc2032be3c91eb30d3f102569ac487bd44b2ba97a4db9fe2c29acbf5e5b",
         "tag": "",
         "filename": "",
         "type": "CHAINLOOP_PR_INFO",
         "Set": true,
         "IsOutput": false,
         "Required": false,
         "SkipUpload": false
      }
   ],
   "envVars": {},
   "runnerContext": {
      "EnvVars": {
         "GITHUB_ACTOR": "testuser",
         "GITHUB_BASE_REF": "main",
         "GITHUB_EVENT_NAME": "pull_request",
         "GITHUB_EVENT_PATH": "/tmp/github_event_pr.json",
         "GITHUB_HEAD_REF": "testing",
         "GITHUB_REF": "refs/pull/12/merge",
         "GITHUB_REPOSITORY": "testuser/chainloop-goreleaser",
         "GITHUB_REPOSITORY_OWNER": "testuser",
         "GITHUB_RUN_ID": "123456789",
         "GITHUB_SHA": "abc123def456",
         "RUNNER_NAME": "GitHub Actions Runner",
         "RUNNER_OS": "Linux"
      },
      "JobURL": "https://github.com/testuser/chainloop-goreleaser/actions/runs/123456789",
      "RunnerType": "GITHUB_ACTION"
   },
   "dryRun": false,
   "annotations": [],
   "isPushed": false,
   "has_policy_violations": false,
   "must_block_on_policy_violations": false,
   "timestamp_authority": "",
   "digest": "",
   "terminal_output": null
}

app/cli/chainloop  push --attestation-id 6dcfb573-d32e-4fc6-8680-bf04e1182199
WRN API contacted in insecure mode
INF push completed
┌───────────────────────────┬─────────────────────────────────────────────────────────────────────────┐
│ Initialized At            │ 08 Jan 26 13:26 UTC                                                     │
├───────────────────────────┼─────────────────────────────────────────────────────────────────────────┤
│ Attestation ID            │ 6dcfb573-d32e-4fc6-8680-bf04e1182199                                    │
│ Digest                    │ sha256:ab0c76f821896820b80e3b14f0ee5568b313773206116db337bd99088bdc0235 │
│ Organization              │ testing                                                                 │
│ Name                      │ pr-validation                                                           │
│ Project                   │ core                                                                    │
│ Version                   │ v1.68.0+next (prerelease)                                               │
│ Contract                  │ core-pr-validation (revision 1)                                         │
│ Runner Type               │ GITHUB_ACTION                                                           │
│ Runner URL                │ https://github.com/testuser/chainloop-goreleaser/actions/runs/123456789 │
│ Policy violation strategy │ ADVISORY                                                                │
└───────────────────────────┴─────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────┐
│ Materials                                                                          │
├──────────┬─────────────────────────────────────────────────────────────────────────┤
│ Name     │ pr-metadata                                                             │
│ Type     │ CHAINLOOP_PR_INFO                                                       │
│ Set      │ Yes                                                                     │
│ Required │ No                                                                      │
│ Value    │ pr-metadata-3862956156.json                                             │
│ Digest   │ sha256:52e97fc2032be3c91eb30d3f102569ac487bd44b2ba97a4db9fe2c29acbf5e5b │
└──────────┴─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ Runner context                                          │
├─────────────────────────┬───────────────────────────────┤
│ GITHUB_ACTOR            │ testuser                      │
│ GITHUB_REF              │ refs/pull/12/merge            │
│ GITHUB_RUN_ID           │ 123456789                     │
│ GITHUB_SHA              │ abc123def456                  │
│ RUNNER_OS               │ Linux                         │
│ GITHUB_EVENT_NAME       │ pull_request                  │
│ GITHUB_HEAD_REF         │ testing                       │
│ GITHUB_REPOSITORY       │ testuser/chainloop-goreleaser │
│ GITHUB_REPOSITORY_OWNER │ testuser                      │
│ RUNNER_NAME             │ GitHub Actions Runner         │
│ GITHUB_BASE_REF         │ main                          │
│ GITHUB_EVENT_PATH       │ /tmp/github_event_pr.json     │
└─────────────────────────┴───────────────────────────────┘

@javirln javirln self-assigned this Jan 8, 2026
@javirln javirln marked this pull request as ready for review January 8, 2026 13:29
// AutoCollectPRMetadata automatically collects PR/MR metadata if running in a PR/MR context
func (c *Crafter) AutoCollectPRMetadata(ctx context.Context, attestationID string, runner SupportedRunner, casBackend *casclient.CASBackend) error {
if err := c.requireStateLoaded(); err != nil {
return fmt.Errorf("crafting state not loaded before inspecting PR/MR metadata: %w", err)
Copy link
Member

Choose a reason for hiding this comment

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

can this ever happen?

Copy link
Member Author

Choose a reason for hiding this comment

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

My take is that since it’s a public method on the crafter, it’s not guaranteed that it’s being called after a state has been loaded. Similarly, the other public methods that interact with the state have the guard, so I’ve added it here as well.

@javirln javirln merged commit 71a78ac into chainloop-dev:main Jan 8, 2026
16 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants