Skip to content

Commit f795bb9

Browse files
committed
publish: the shape-pins hold the promotion gate to the tags' own naming
1 parent 8d4660d commit f795bb9

2 files changed

Lines changed: 33 additions & 16 deletions

File tree

‎.github/workflows/publish.yml‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ jobs:
6262
publish:
6363
runs-on: ubuntu-latest
6464
outputs:
65-
image_repo: ${{ steps.ref.outputs.image_repo }}
65+
repo: ${{ steps.ref.outputs.repo }}
6666
example: ${{ steps.guard.outputs.example }}
6767
version: ${{ steps.ref.outputs.version }}
6868
staging: ${{ steps.ref.outputs.staging }}
@@ -129,13 +129,13 @@ jobs:
129129
set -euo pipefail
130130
owner=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
131131
version=$(grep -m1 '^version = ' Cargo.toml | cut -d'"' -f2)
132-
image_repo="ghcr.io/$owner/kuma"
132+
repo="ghcr.io/$owner/kuma"
133133
{
134-
echo "image_repo=$image_repo"
134+
echo "repo=$repo"
135135
echo "version=$version"
136-
echo "staging=$image_repo:${{ steps.guard.outputs.example }}-staging"
137-
echo "remote=$image_repo:${{ steps.guard.outputs.example }}"
138-
echo "pinned=$image_repo:${{ steps.guard.outputs.example }}-$version"
136+
echo "staging=$repo:${{ steps.guard.outputs.example }}-staging"
137+
echo "remote=$repo:${{ steps.guard.outputs.example }}"
138+
echo "pinned=$repo:${{ steps.guard.outputs.example }}-$version"
139139
echo "local=localhost/kuma-publish:${{ steps.guard.outputs.example }}"
140140
} >> "$GITHUB_OUTPUT"
141141
@@ -315,7 +315,7 @@ jobs:
315315
316316
- name: move the tags
317317
env:
318-
IMAGE_REPO: ${{ needs.publish.outputs.image_repo }}
318+
IMAGE_REPO: ${{ needs.publish.outputs.repo }}
319319
DIGEST: ${{ needs.publish.outputs.digest }}
320320
EXAMPLE: ${{ needs.publish.outputs.example }}
321321
VERSION: ${{ needs.publish.outputs.version }}

‎src/config.rs‎

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,12 +1511,18 @@ pub(crate) mod tests {
15111511
super::documented_commands("docs/getting-started.md")
15121512
}
15131513

1514-
/// Publishing moves the mutable tag, and three of the four jobs that
1515-
/// validate a published image read that tag. So dispatching them
1516-
/// before a publish re-tests the previous release, and the mechanism
1517-
/// keeping the order right was somebody remembering it: for v0.11.0
1518-
/// the validation was simply never run, and its cross-version job
1519-
/// still holds an unanswered question about that release.
1514+
/// Publishing gates the mutable tag on the validation. The laps
1515+
/// install and boot the digest-pinned staging ref this run pushed;
1516+
/// the promote job moves the tags people pull only if every lap came
1517+
/// back green. Two of the first three publishes failed their
1518+
/// validations after the tags were already live (44.3.0's
1519+
/// signatures, 44.6.0's greeter) — under the old order the laps
1520+
/// could tell somebody the same day, but what they said was that
1521+
/// the broken thing was public. Composes of one commit are not
1522+
/// byte-stable (src/lock.rs: layered packages resolve live on
1523+
/// purpose), so gating on "the same image built again" is not an
1524+
/// option: the bytes that go live must be the bytes that were
1525+
/// validated.
15201526
#[test]
15211527
fn publishing_triggers_the_workflow_that_validates_what_was_published() {
15221528
let read = |name: &str| {
@@ -1533,11 +1539,22 @@ pub(crate) mod tests {
15331539
);
15341540
assert!(
15351541
publish.contains("needs: publish"),
1536-
"the validation runs after the publish, so nothing it finds can unpublish anything"
1542+
"the validation runs after the staging push, so the laps see this run's bytes"
15371543
);
15381544
assert!(
1539-
publish.contains("image: ${{ needs.publish.outputs.remote }}"),
1540-
"the validation should test the image this run published, not a default"
1545+
publish
1546+
.contains("image: ${{ needs.publish.outputs.staging }}@${{ needs.publish.outputs.digest }}"),
1547+
"the validation should install the digest-pinned staging ref, not a default and not an unpinned tag: \
1548+
a tag can move under a concurrent publish and put different bytes under this run's verdict"
1549+
);
1550+
assert!(
1551+
publish.contains("needs: [publish, validate]"),
1552+
"the promote job waits on the validation: the tags move only when every lap is green"
1553+
);
1554+
assert!(
1555+
publish.contains("crane tag"),
1556+
"the promotion re-points the tags at the validated digest without moving bytes, \
1557+
so the digest the signature names is the digest the tags serve"
15411558
);
15421559
assert!(
15431560
read("published.yml").contains("workflow_call:"),

0 commit comments

Comments
 (0)