Skip to content

Commit e1b106c

Browse files
committed
Release pipeline: draft → verify → publish flow
Restructured release to prevent unverified binaries from being public: 1. release-draft: create draft release (not visible to users) 2. verify: VirusTotal scan + OpenSSF Scorecard on draft binaries 3. If verification passes: append results to notes + publish 4. If verification fails: draft stays unpublished
1 parent 2e21a01 commit e1b106c

File tree

1 file changed

+16
-18
lines changed

1 file changed

+16
-18
lines changed

.github/workflows/release.yml

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,8 @@ jobs:
339339
shell: msys2 {0}
340340
run: scripts/security-install.sh ./codebase-memory-mcp.exe
341341

342-
# ── Step 5: Create GitHub release ───────────────────────────
343-
release:
342+
# ── Step 5: Create DRAFT release (not public yet) ─────────────
343+
release-draft:
344344
needs: [smoke-unix, smoke-windows, security-static]
345345
runs-on: ubuntu-latest
346346
permissions:
@@ -361,9 +361,6 @@ jobs:
361361
run: sha256sum *.tar.gz *.zip > checksums.txt
362362

363363
# ── Artifact attestations (SLSA provenance) ──────────────
364-
# Cryptographically proves each binary was built by this
365-
# GitHub Actions workflow from this repo. Verifiable with:
366-
# gh attestation verify <file> --repo DeusData/codebase-memory-mcp
367364
- name: Attest build provenance (tar.gz)
368365
uses: actions/attest-build-provenance@v2
369366
with:
@@ -380,7 +377,6 @@ jobs:
380377
subject-path: 'checksums.txt'
381378

382379
# ── SBOM generation ──────────────────────────────────────
383-
# Software Bill of Materials listing all vendored dependencies.
384380
- name: Generate SBOM
385381
run: |
386382
cat > sbom.json << 'SBOMEOF'
@@ -414,8 +410,6 @@ jobs:
414410
sbom-path: 'sbom.json'
415411

416412
# ── Sigstore cosign signing ──────────────────────────────
417-
# Keyless signing via GitHub OIDC identity. Verifiable with:
418-
# cosign verify-blob --bundle <file>.bundle <file>
419413
- name: Install cosign
420414
uses: sigstore/cosign-installer@v3
421415

@@ -425,7 +419,7 @@ jobs:
425419
cosign sign-blob --yes --bundle "${f}.bundle" "$f"
426420
done
427421
428-
# ── Create release ───────────────────────────────────────
422+
# ── Create DRAFT release (not visible to users yet) ──────
429423
- name: Delete existing release
430424
if: ${{ inputs.replace }}
431425
env:
@@ -443,6 +437,7 @@ jobs:
443437
- uses: softprops/action-gh-release@v2
444438
with:
445439
tag_name: ${{ inputs.version }}
440+
draft: true
446441
files: |
447442
*.tar.gz
448443
*.zip
@@ -452,11 +447,12 @@ jobs:
452447
body: ${{ inputs.release_notes || '' }}
453448
generate_release_notes: ${{ inputs.release_notes == '' }}
454449

455-
# ── Step 6: Post-release security verification ───────────────
456-
# Scans binaries with VirusTotal, runs OpenSSF Scorecard,
457-
# and appends all results to the release notes.
450+
# ── Step 6: Verify draft release ─────────────────────────────
451+
# Scans binaries with VirusTotal, runs OpenSSF Scorecard.
452+
# If verification passes, appends results and publishes.
453+
# If it fails, the draft stays unpublished.
458454
verify:
459-
needs: [release]
455+
needs: [release-draft]
460456
runs-on: ubuntu-latest
461457
permissions:
462458
contents: write
@@ -468,7 +464,7 @@ jobs:
468464
persist-credentials: false
469465

470466
# ── VirusTotal scan ──────────────────────────────────────
471-
- name: Download release binaries
467+
- name: Download draft release binaries
472468
env:
473469
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
474470
VERSION: ${{ inputs.version }}
@@ -503,7 +499,6 @@ jobs:
503499
- name: Extract Scorecard score
504500
id: score
505501
run: |
506-
# Extract overall score from SARIF (properties.score)
507502
SCORE=$(python3 -c "
508503
import json, sys
509504
with open('scorecard.sarif') as f:
@@ -514,8 +509,8 @@ jobs:
514509
echo "score=$SCORE" >> "$GITHUB_OUTPUT"
515510
echo "OpenSSF Scorecard: $SCORE/10"
516511
517-
# ── Append all results to release notes ──────────────────
518-
- name: Append security verification to release notes
512+
# ── Append results + publish ─────────────────────────────
513+
- name: Append security verification and publish release
519514
env:
520515
VT_ANALYSIS: ${{ steps.virustotal.outputs.analysis }}
521516
SCORECARD_SCORE: ${{ steps.score.outputs.score }}
@@ -557,4 +552,7 @@ jobs:
557552
EXISTING=$(gh release view "$VERSION" --json body --jq '.body' --repo "$GITHUB_REPOSITORY")
558553
printf '%s\n\n%s\n' "$EXISTING" "$REPORT" | gh release edit "$VERSION" --notes-file - --repo "$GITHUB_REPOSITORY"
559554
560-
echo "=== Security verification appended to release notes ==="
555+
# ── Publish: promote draft to public release ─────────
556+
gh release edit "$VERSION" --draft=false --repo "$GITHUB_REPOSITORY"
557+
558+
echo "=== Release verified and published ==="

0 commit comments

Comments
 (0)