Merge remote-tracking branch 'origin/main' into claude/amazing-thompson-bgplnq
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SSVQGR4WU92LaddTP19GcQ
This commit is contained in:
commit
b38e410fa3
18
.github/workflows/publish-server-image.yml
vendored
18
.github/workflows/publish-server-image.yml
vendored
@ -256,9 +256,23 @@ jobs:
|
|||||||
grep -Fqx "$want" <<< "$platforms" || { echo "$first_tag is missing $want" >&2; exit 1; }
|
grep -Fqx "$want" <<< "$platforms" || { echo "$first_tag is missing $want" >&2; exit 1; }
|
||||||
done
|
done
|
||||||
echo "digest=$(docker buildx imagetools inspect "$first_tag" --format '{{.Manifest.Digest}}')" >> "$GITHUB_OUTPUT"
|
echo "digest=$(docker buildx imagetools inspect "$first_tag" --format '{{.Manifest.Digest}}')" >> "$GITHUB_OUTPUT"
|
||||||
# GitHub artifact attestations are unavailable for private repos on personal accounts.
|
# Owner type is not exposed on the github context; resolve it from the repository metadata API.
|
||||||
|
- name: Resolve registry attestation eligibility
|
||||||
|
id: attestation
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
owner_type="$(gh api "repos/${GITHUB_REPOSITORY}" --jq -r '.owner.type')"
|
||||||
|
private="$(gh api "repos/${GITHUB_REPOSITORY}" --jq -r '.private')"
|
||||||
|
if [[ "$owner_type" == "User" && "$private" == "true" ]]; then
|
||||||
|
echo "enabled=false" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Skipping registry attestation: unavailable for private repositories on personal accounts."
|
||||||
|
else
|
||||||
|
echo "enabled=true" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
- name: Attest the published image
|
- name: Attest the published image
|
||||||
if: github.event.repository.private != true || github.repository_owner_type != 'User'
|
if: steps.attestation.outputs.enabled == 'true'
|
||||||
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
|
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
|
||||||
with:
|
with:
|
||||||
subject-name: ghcr.io/${{ steps.ns.outputs.repo }}/${{ matrix.name }}
|
subject-name: ghcr.io/${{ steps.ns.outputs.repo }}/${{ matrix.name }}
|
||||||
|
|||||||
@ -38,12 +38,14 @@ describe("server image publish workflow", () => {
|
|||||||
expect(publish.needs).toBe("build");
|
expect(publish.needs).toBe("build");
|
||||||
expect(workflowText).toContain("push-by-digest=true");
|
expect(workflowText).toContain("push-by-digest=true");
|
||||||
expect(workflowText).toContain("docker buildx imagetools create");
|
expect(workflowText).toContain("docker buildx imagetools create");
|
||||||
expect(workflowText).toContain('if [[ "${#sources[@]}" -ne 1 ]]');
|
expect(workflowText).toContain(`if [[ "\${#sources[@]}" -ne 1 ]]`);
|
||||||
expect(workflowText).toContain("for want in linux/amd64; do");
|
expect(workflowText).toContain("for want in linux/amd64; do");
|
||||||
expect(workflowText).toContain("actions/attest-build-provenance@");
|
expect(workflowText).toContain("actions/attest-build-provenance@");
|
||||||
expect(workflowText).toContain(
|
expect(workflowText).not.toContain("github.repository_owner_type");
|
||||||
"if: github.event.repository.private != true || github.repository_owner_type != 'User'",
|
expect(workflowText).toContain(`gh api "repos/\${GITHUB_REPOSITORY}"`);
|
||||||
);
|
expect(workflowText).toContain(".owner.type");
|
||||||
|
expect(workflowText).toContain("if: steps.attestation.outputs.enabled == 'true'");
|
||||||
|
expect(workflowText).toContain('[[ "$owner_type" == "User" && "$private" == "true" ]]');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("stores digest markers under RUNNER_TEMP so self-hosted runners do not leak stale files", () => {
|
it("stores digest markers under RUNNER_TEMP so self-hosted runners do not leak stale files", () => {
|
||||||
@ -52,11 +54,11 @@ describe("server image publish workflow", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("names every image under the lowercase repository namespace", () => {
|
it("names every image under the lowercase repository namespace", () => {
|
||||||
expect(workflowText).not.toContain("ghcr.io/${{ github.repository }}");
|
expect(workflowText).not.toContain(`ghcr.io/\${{ github.repository }}`);
|
||||||
const references =
|
const references =
|
||||||
workflowText.match(/ghcr\.io\/\$\{\{ steps\.ns\.outputs\.repo \}\}\//g) ?? [];
|
workflowText.match(/ghcr\.io\/\$\{\{ steps\.ns\.outputs\.repo \}\}\//g) ?? [];
|
||||||
expect(references.length).toBeGreaterThanOrEqual(6);
|
expect(references.length).toBeGreaterThanOrEqual(6);
|
||||||
expect(workflowText).toContain("repo=${GITHUB_REPOSITORY,,}");
|
expect(workflowText).toContain(`repo=\${GITHUB_REPOSITORY,,}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("keeps pull requests read-only and every action pinned to a commit", () => {
|
it("keeps pull requests read-only and every action pinned to a commit", () => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user