From d54e2fe276d994572075ba655530e4df8cd51fb1 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 8 Nov 2026 02:32:03 +0000 Subject: [PATCH] release: the PC stick image, and a Gitea release anyone can download from (#126) - scripts/nightly.sh images builds the PC's USB stick too (make boot_image TARGET=PC -> pc-stick.img.xz, in SHA256SUMS); publish sends it to Nexus as classifier pc-stick. pc stays the ISO QEMU boots. - scripts/nightly.sh gitea-release : the tag as a Gitea release -- a pre-release for -alpha.N and the like -- notes from the tag's message with the checksums, the images, SHA256SUMS, the documents and the StarshipOS Root CA's certificate attached; run again, it adds only what is missing. release.yml runs it after the Nexus publish, with the secret RELEASE_TOKEN. Tested here: images builds pc-stick.img.xz (785 KB); gitea-release against a stand-in Gitea API made a pre-release with the notes and ten files, and a second run added nothing. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2 --- .gitea/workflows/nightly.yml | 1 + .gitea/workflows/release.yml | 12 +++++++- scripts/nightly.sh | 53 +++++++++++++++++++++++++++++++----- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/.gitea/workflows/nightly.yml b/.gitea/workflows/nightly.yml index 8cc718cc..8c958766 100644 --- a/.gitea/workflows/nightly.yml +++ b/.gitea/workflows/nightly.yml @@ -6,6 +6,7 @@ # # org.starship:kernelImage:-SNAPSHOT, starshipos-snapshots # classifier pc StarshipOS.iso amd64, UEFI -- the ISO the amd64 acceptance boot booted +# classifier pc-stick pc-stick.img.xz a PC's USB stick, for any UEFI PC (make boot_image TARGET=PC) # classifier raspi5 raspi5.img.xz Raspberry Pi 5, for Raspberry Pi Imager # classifier milkv MilkV.img.xz Milk-V Mars # classifier logs logs.tar.gz this run's serial logs and DoE CSVs (the proof log is in diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index e58d82bd..04e5509a 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -2,9 +2,14 @@ # acceptance protocol, the proofs, the board images -- and the documents, and publishes both to # starshipos-releases at that version: # -# org.starship:kernelImage: classifiers pc, raspi5, milkv, logs (nightly.yml) +# org.starship:kernelImage: classifiers pc, pc-stick, raspi5, milkv, logs (nightly.yml) # org.starship:documentation: classifiers book, vol1, vol2, vol3, api (nightly-docs.yml) # +# and makes the tag a Gitea release -- a pre-release for v-alpha.N and the like -- with the +# images, SHA256SUMS, the documents and the StarshipOS Root CA's certificate attached, for anyone +# to download (#126; scripts/nightly.sh gitea-release). Needs the secret RELEASE_TOKEN: a token +# that may write the repository. +# # The tag must name the version the tree says it is: v (kernel/Makefile). A tag # that does not is refused before anything is built. A release repository takes a version once. name: Release @@ -84,6 +89,11 @@ jobs: scripts/nightly.sh publish https://nexus.starshipos-f18.org/repository/starshipos-releases scripts/nightly.sh publish-docs https://nexus.starshipos-f18.org/repository/starshipos-releases + - name: Gitea release # the downloads anyone can fetch (#126): no Nexus login + env: + RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} # a token that may write the repository + run: scripts/nightly.sh gitea-release "${{ github.ref_name }}" + - name: Keep the release uses: actions/upload-artifact@v3 with: diff --git a/scripts/nightly.sh b/scripts/nightly.sh index 49a7b2ca..f7bfad37 100755 --- a/scripts/nightly.sh +++ b/scripts/nightly.sh @@ -22,6 +22,7 @@ # logs//isabelle/, as a boot's is. # scripts/nightly.sh images # The board images, into build/nightly/: +# pc-stick.img.xz a PC's USB stick (make boot_image TARGET=PC): GPT, one ESP, any UEFI PC # raspi5.img.xz Raspberry Pi 5 (make boot_image TARGET=RASPI), for Raspberry Pi Imager # MilkV.img.xz Milk-V Mars (make boot_image TARGET=MILKV) # SHA256SUMS of StarshipOS.iso and both images, before and after compression @@ -29,7 +30,7 @@ # same sources, for hardware QEMU does not model. # scripts/nightly.sh publish # org.starship:kernelImage: to that Maven repository, in one deploy (one -# timestamp): classifier pc (iso), raspi5 and milkv (img.xz), and logs (tar.gz: this +# timestamp): classifier pc (iso, for QEMU), pc-stick, raspi5 and milkv (img.xz), and logs (tar.gz: this # run's serial logs and DoE CSVs -- the evidence for the rest; and the proof log, when the # proofs ran before it, as a release runs them). # @@ -54,7 +55,7 @@ LITHOS=$(sed -n 's/^LITHOS_VERSION *?= *//p' kernel/Makefile) VERSION=${NIGHTLY_VERSION:-$LITHOS-SNAPSHOT} usage() { echo "Usage: scripts/nightly.sh accept | test-32 | proofs | images" >&2 - echo " | publish | docs | publish-docs " >&2 + echo " | publish | docs | publish-docs | gitea-release " >&2 exit 2 } need() { for f in "$@"; do [ -f "$f" ] || { echo "nightly: no $f -- run the stages before this one" >&2; exit 1; }; done; } @@ -138,7 +139,7 @@ proofs) ;; images) need "$OUT/StarshipOS.iso" - for b in "RASPI raspi/lithos-raspi.img raspi5.img" "MILKV milkv/lithos-milkv.img MilkV.img"; do + for b in "PC pc/lithos-pc.img pc-stick.img" "RASPI raspi/lithos-raspi.img raspi5.img" "MILKV milkv/lithos-milkv.img MilkV.img"; do set -- $b echo "=== nightly: image $1" make --no-print-directory boot_image TARGET="$1" @@ -147,18 +148,20 @@ images) # boot_image regenerates these (the source SBOM, and what qemu_session.py also puts back); # the nightly does not change the tree git checkout -q -- sbom.spdx sbom.spdx.json capsules/BLOCK_MAP.md v3/include/version.h - (cd "$OUT" && rm -f raspi5.img.xz MilkV.img.xz && sha256sum StarshipOS.iso raspi5.img MilkV.img > SHA256SUMS) - xz -T0 -6 "$OUT/raspi5.img" "$OUT/MilkV.img" - (cd "$OUT" && sha256sum raspi5.img.xz MilkV.img.xz >> SHA256SUMS && cat SHA256SUMS) + (cd "$OUT" && rm -f pc-stick.img.xz raspi5.img.xz MilkV.img.xz && + sha256sum StarshipOS.iso pc-stick.img raspi5.img MilkV.img > SHA256SUMS) + xz -T0 -6 "$OUT/pc-stick.img" "$OUT/raspi5.img" "$OUT/MilkV.img" + (cd "$OUT" && sha256sum pc-stick.img.xz raspi5.img.xz MilkV.img.xz >> SHA256SUMS && cat SHA256SUMS) ;; publish) url=${2:-}; [ -n "$url" ] || usage - need "$OUT/StarshipOS.iso" "$OUT/raspi5.img.xz" "$OUT/MilkV.img.xz" + need "$OUT/StarshipOS.iso" "$OUT/pc-stick.img.xz" "$OUT/raspi5.img.xz" "$OUT/MilkV.img.xz" # the evidence: what this run wrote under logs/ and experiments/bare_metal/runs/ find logs experiments/bare_metal/runs -type f -newer "$OUT/.started" -print0 \ | tar --null -czf "$OUT/logs.tar.gz" -T - echo "=== nightly: logs.tar.gz: $(tar -tzf "$OUT/logs.tar.gz" | wc -l) files" deploy "$url" kernelImage "$OUT/StarshipOS.iso" iso pc \ + "$OUT/pc-stick.img.xz" img.xz pc-stick \ "$OUT/raspi5.img.xz" img.xz raspi5 \ "$OUT/MilkV.img.xz" img.xz milkv \ "$OUT/logs.tar.gz" tar.gz logs @@ -172,6 +175,42 @@ docs) cp docs/formal/build/doxygen/StarForth-API-Reference.pdf "$DOCS/api.pdf" (cd "$DOCS" && sha256sum ./*.pdf | tee SHA256SUMS) ;; +gitea-release) + # The release as Gitea's own (#126): a release for -- a pre-release when the tag names + # one (v4.0.0-alpha.3) -- its notes the tag's message and the checksums, its files everyone's + # to download from the public repository, no Nexus login: the images, SHA256SUMS, the + # documents, and the StarshipOS Root CA's certificate (FABRIC-3 XLVI). Run again, it adds what + # is missing and changes nothing else. RELEASE_TOKEN: a token that may write the repository. + tag=${2:-}; [ -n "$tag" ] || usage + : "${RELEASE_TOKEN:?RELEASE_TOKEN: a token that may write the repository}" + api=${GITEA_API:-${GITHUB_SERVER_URL:-https://gitea.starshipos-f18.org}/api/v1/repos/${GITHUB_REPOSITORY:-rajames/LithosAnanke}} + need "$OUT/StarshipOS.iso" "$OUT/pc-stick.img.xz" "$OUT/raspi5.img.xz" "$OUT/MilkV.img.xz" "$OUT/SHA256SUMS" + files=("$OUT/StarshipOS.iso" "$OUT/pc-stick.img.xz" "$OUT/raspi5.img.xz" "$OUT/MilkV.img.xz" "$OUT/SHA256SUMS") + for f in "$DOCS"/*.pdf ci/pki/starshipos-root-ca.pem; do [ -f "$f" ] && files+=("$f"); done + gitea() { curl -fsS -H "Authorization: token $RELEASE_TOKEN" "$@"; } + body=$(python3 -c ' +import json, sys +notes, sums, version = sys.argv[1], open(sys.argv[2]).read(), sys.argv[3] +print(json.dumps(notes.strip() + "\n\n## Checksums (SHA-256)\n\n```\n" + sums.strip() + "\n```\n\n" + "Also in Nexus: `org.starship:kernelImage:" + version + "` and `org.starship:documentation:" + version + "`.\n"))' \ + "$(git tag -l --format='%(contents)' "$tag")" "$OUT/SHA256SUMS" "$VERSION") + id=$(gitea "$api/releases/tags/$tag" 2>/dev/null | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])' 2>/dev/null || true) + if [ -z "$id" ]; then + pre=false; case "$tag" in *-*) pre=true;; esac + id=$(gitea -X POST -H 'Content-Type: application/json' "$api/releases" \ + -d "{\"tag_name\": \"$tag\", \"name\": \"$tag\", \"prerelease\": $pre, \"body\": $body}" | + python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])') + echo "=== nightly: Gitea release $tag made (id $id, pre-release $pre)" + else + echo "=== nightly: Gitea release $tag is there (id $id)" + fi + have=$(gitea "$api/releases/$id/assets" | python3 -c 'import json,sys; print(" ".join(a["name"] for a in json.load(sys.stdin)))') + for f in "${files[@]}"; do + n=$(basename "$f") + case " $have " in *" $n "*) echo " $n: there"; continue;; esac + gitea -o /dev/null -X POST -F "attachment=@$f" "$api/releases/$id/assets?name=$n" && echo " $n: attached" + done + ;; publish-docs) url=${2:-}; [ -n "$url" ] || usage need "$DOCS/book.pdf" "$DOCS/vol1.pdf" "$DOCS/vol2.pdf" "$DOCS/vol3.pdf" "$DOCS/api.pdf"