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
6 changes: 6 additions & 0 deletions .github/workflows/cargo-runtime-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ on:
description: "Exact workflow identity that attested the base rootfs."
required: true
type: string
attest-runtime-image:
description: "Publish GitHub build provenance for the derived runtime image. Disable for repositories where GitHub artifact attestations are unavailable."
required: false
type: boolean
default: true
bootstrap-mode:
required: false
type: string
Expand Down Expand Up @@ -230,6 +235,7 @@ jobs:
"${RUNNER_TEMP}/cargo-runtime-image-two.tar.xz"

- name: Attest deterministic Cargo runtime image
if: ${{ inputs.attest-runtime-image }}
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a
with:
subject-path: ${{ runner.temp }}/cargo-runtime-image-one.tar.xz
Expand Down
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,19 @@ each build at the declared absolute path, normalizes the rootfs archive, rejects
any embedded `liskov-runtime-contact`, and requires both complete images to
have the same digest and bytes.

Only after that proof does the workflow attest the generated image, import the
exact authored manifest, and invoke the existing scoped upload/finalization
action. Callers must pin the base image's SHA-256, source commit, repository,
and signer workflow. Release callers should use the maintained promoted rootfs;
a release-candidate rootfs remains suitable only for an explicitly controlled
Only after that proof does the workflow optionally attest the generated image,
import the exact authored manifest, and invoke the existing scoped
upload/finalization action. Generated-image attestation defaults on. Set
`attest-runtime-image: false` when GitHub artifact attestations are unavailable,
including private repositories whose organization plan does not provide them.
This skips only publication of GitHub build provenance for the derived image:
Liskov still verifies the caller's GitHub OIDC identity and binds the exact
Application, manifest digest pair, source commit, workflow, and image digest.
The base image remains digest- and attestation-verified in both modes.

Callers must pin the base image's SHA-256, source commit, repository, and signer
workflow. Release callers should use the maintained promoted rootfs; a
release-candidate rootfs remains suitable only for an explicitly controlled
canary.

```yaml
Expand All @@ -172,6 +180,7 @@ jobs:
base-attestation-repository: proof-computer/liskov-runtime-images
base-attestation-source-digest: <exact source commit>
base-attestation-signer-workflow: proof-computer/liskov-runtime-images/.github/workflows/ci.yml
attest-runtime-image: false # optional; defaults to true
```

## À-la-carte actions
Expand Down Expand Up @@ -201,6 +210,9 @@ Compose your own job from these (`uses: proof-computer/liskov-github-actions/act
- `v1.2.0` adds backward-compatible caller-prepared artifact bytes, sanitized
Diagnostic metadata, existing-CID gateway verification, multi-target artifact-pin
attestation, reusable-workflow outputs, and durable build-manifest run artifacts.
- `v1.2.3` allows Cargo callers to skip publishing derived-image GitHub build
provenance while retaining deterministic byte proof, base-image attestation,
and Liskov's exact OIDC/manifest/image binding.
- Reusable workflows reference their own JS actions by the literal `@v1` major tag,
so a caller pinned to `@v1` executes the matching released action surface.

Expand Down
9 changes: 8 additions & 1 deletion actions/runtime-image-upload/src/cargo-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ import { describe, it } from "node:test";
import { parse } from "yaml";

describe("Cargo runtime-image reusable workflow", () => {
it("pins inputs, proves two builds, attests, then finalizes", async () => {
it("pins inputs, proves two builds, optionally attests, then finalizes", async () => {
const path = new URL("../../../.github/workflows/cargo-runtime-image.yml", import.meta.url);
const workflow = parse(await readFile(path, "utf8")) as Record<string, unknown>;
const trigger = object(workflow.on, "on");
const workflowCall = object(trigger.workflow_call, "workflow_call");
const inputs = object(workflowCall.inputs, "inputs");
const attestInput = object(inputs["attest-runtime-image"], "attest-runtime-image");
assert.equal(attestInput.type, "boolean");
assert.equal(attestInput.default, true);
const jobs = object(workflow.jobs, "jobs");
const job = object(jobs["build-upload"], "build-upload");
assert.equal(job["runs-on"], "ubuntu-24.04-arm");
Expand All @@ -32,6 +38,7 @@ describe("Cargo runtime-image reusable workflow", () => {
steps[attest]?.uses,
"actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a"
);
assert.equal(steps[attest]?.if, "${{ inputs.attest-runtime-image }}");
assert.equal(
steps[upload]?.uses,
"proof-computer/liskov-github-actions/actions/runtime-image-upload@v1"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "liskov-github-actions",
"version": "1.2.2",
"version": "1.2.3",
"private": true,
"type": "module",
"description": "Reusable GitHub Actions + workflows for Liskov CI: manifest-bound artifact and runtime-image publication plus marketplace OIDC ingest.",
Expand Down
Loading