name: Sanctum Release on: push: tags: - 'v*' jobs: # SA-02 & SA-04: Entkoppelte Build- & Test-Umgebung ohne Zugriff auf Signatur-Secrets build: name: Build & Test (Windows x86_64 & Linux musl) runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install Rust toolchain uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master commit pinned with: toolchain: "1.85.0" targets: x86_64-pc-windows-gnu,x86_64-unknown-linux-musl - name: Install cargo-zigbuild (pinned, hash-verified) shell: bash run: | set -euo pipefail ZIGBUILD_VERSION="0.23.4" ZIGBUILD_URL="https://github.com/rust-cross/cargo-zigbuild/releases/download/v${ZIGBUILD_VERSION}/cargo-zigbuild-x86_64-unknown-linux-musl.tar.xz" EXPECTED_HASH="9e3cf73485edbd45905c8aadbc0fdf869c7ddc3848f0c898229f2680db52e44b" curl -fsSL "$ZIGBUILD_URL" -o cargo-zigbuild.tar.xz ACTUAL_HASH=$(sha256sum cargo-zigbuild.tar.xz | awk '{print $1}') if [ "$ACTUAL_HASH" != "$EXPECTED_HASH" ]; then echo "KRITISCHER SICHERHEITSFEHLER: cargo-zigbuild SHA-256 Pruefsumme ungueltig! Erwartet: $EXPECTED_HASH, Erhalten: $ACTUAL_HASH" >&2 exit 1 fi tar -xJf cargo-zigbuild.tar.xz --strip-components=1 -C "$HOME/.cargo/bin" cargo-zigbuild-x86_64-unknown-linux-musl/cargo-zigbuild rm -f cargo-zigbuild.tar.xz - name: Install Zig (pinned, hash-verified) shell: bash run: | set -euo pipefail ZIG_VERSION="0.16.0" ZIG_URL="https://ziglang.org/download/${ZIG_VERSION}/zig-x86_64-linux-${ZIG_VERSION}.tar.xz" EXPECTED_ZIG_HASH="70e49664a74374b48b51e6f3fdfbf437f6395d42509050588bd49abe52ba3d00" curl -fsSL "$ZIG_URL" -o zig.tar.xz ACTUAL_HASH=$(sha256sum zig.tar.xz | awk '{print $1}') if [ "$ACTUAL_HASH" != "$EXPECTED_ZIG_HASH" ]; then echo "KRITISCHER SICHERHEITSFEHLER: Zig SHA-256 Pruefsumme ungueltig! Erwartet: $EXPECTED_ZIG_HASH, Erhalten: $ACTUAL_HASH" >&2 exit 1 fi mkdir -p zig-bin tar -xJf zig.tar.xz -C zig-bin rm -f zig.tar.xz echo "$PWD/zig-bin/zig-x86_64-linux-${ZIG_VERSION}" >> "$GITHUB_PATH" - name: Run Native Tests run: cargo test --all --verbose - name: Verify Windows Tests Compile run: cargo-zigbuild zigbuild --target x86_64-pc-windows-gnu --tests - name: Cross-build Windows x86_64 Release Binary run: cargo-zigbuild zigbuild --target x86_64-pc-windows-gnu --release - name: Cross-build Linux musl Release Binary run: cargo-zigbuild zigbuild --target x86_64-unknown-linux-musl --release - name: Package Artifacts id: package shell: bash run: | set -euo pipefail TAG="${{ gitea.ref_name }}" DIST_DIR="dist" mkdir -p "$DIST_DIR" # Ensure zip is available if ! command -v zip >/dev/null 2>&1; then sudo apt-get update && sudo apt-get install -y zip fi # 1. Windows Package PACKAGE_NAME_WIN="sanctum-${TAG}-windows-x86_64" STAGING_DIR_WIN="${DIST_DIR}/${PACKAGE_NAME_WIN}" ZIP_FILE="${DIST_DIR}/${PACKAGE_NAME_WIN}.zip" mkdir -p "$STAGING_DIR_WIN" cp "target/x86_64-pc-windows-gnu/release/sanctum.exe" "$STAGING_DIR_WIN/" cp README.md LICENSE CHANGELOG.md QUICKSTART.md INSTALL.md LEGAL.md THIRD_PARTY_LICENSES.md "$STAGING_DIR_WIN/" if [ -d "assets" ]; then cp -r assets "$STAGING_DIR_WIN/" fi (cd "$STAGING_DIR_WIN" && zip -r "../${PACKAGE_NAME_WIN}.zip" .) rm -rf "$STAGING_DIR_WIN" # Standalone Windows EXE nach dist/ kopieren cp "target/x86_64-pc-windows-gnu/release/sanctum.exe" "${DIST_DIR}/sanctum.exe" # 2. Linux Package PACKAGE_NAME_LINUX="sanctum-${TAG}-linux-x86_64" STAGING_DIR_LINUX="${DIST_DIR}/${PACKAGE_NAME_LINUX}" TAR_GZ_FILE="${DIST_DIR}/${PACKAGE_NAME_LINUX}.tar.gz" mkdir -p "$STAGING_DIR_LINUX" cp "target/x86_64-unknown-linux-musl/release/sanctum" "$STAGING_DIR_LINUX/sanctum" chmod +x "$STAGING_DIR_LINUX/sanctum" cp README.md LICENSE CHANGELOG.md QUICKSTART.md INSTALL.md LEGAL.md THIRD_PARTY_LICENSES.md "$STAGING_DIR_LINUX/" tar -czf "$TAR_GZ_FILE" -C "$DIST_DIR" "$PACKAGE_NAME_LINUX" rm -rf "$STAGING_DIR_LINUX" # Standalone Linux ELF nach dist/ kopieren cp "target/x86_64-unknown-linux-musl/release/sanctum" "${DIST_DIR}/sanctum" chmod +x "${DIST_DIR}/sanctum" # 3. SHA-256 Checksums für alle 4 Assets ZIP_HASH=$(sha256sum "$ZIP_FILE" | awk '{print $1}') EXE_HASH=$(sha256sum "${DIST_DIR}/sanctum.exe" | awk '{print $1}') TAR_HASH=$(sha256sum "$TAR_GZ_FILE" | awk '{print $1}') ELF_HASH=$(sha256sum "${DIST_DIR}/sanctum" | awk '{print $1}') cat < "${DIST_DIR}/SHA256SUMS.txt" ${ZIP_HASH} ${PACKAGE_NAME_WIN}.zip ${EXE_HASH} sanctum.exe ${TAR_HASH} ${PACKAGE_NAME_LINUX}.tar.gz ${ELF_HASH} sanctum EOF echo "ZIP_FILE=$ZIP_FILE" >> "$GITHUB_OUTPUT" echo "PACKAGE_NAME=$PACKAGE_NAME_WIN" >> "$GITHUB_OUTPUT" - name: Upload Build Artifacts uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: dist-artifacts path: dist/ # SA-02, SA-03 & SA-04: Dedizierter Signatur- & Release-Job mit isolierten Secrets und Prüfsummen-Verifikation sign-and-release: name: Sign & Release needs: [build] runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/v') steps: - name: Checkout Code (for CHANGELOG.md) uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Download Build Artifacts uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: dist-artifacts path: dist - name: Verify and Sign Checksums with Minisign shell: bash env: MINISIGN_SECRET_KEY: ${{ secrets.MINISIGN_SECRET_KEY }} run: | set -euo pipefail # SA-02: Secret-Isolation — MINISIGN_SECRET_KEY ist ausschließlich in diesem dedizierten Signier-Job verfügbar if [ -z "${MINISIGN_SECRET_KEY:-}" ]; then echo "Secret MINISIGN_SECRET_KEY ist nicht gesetzt! Release ohne Signatur verboten." >&2 exit 1 fi # SA-03: Pinned Download-Integrität für minisign mit zwingender SHA-256 Validierung MINISIGN_URL="https://github.com/jedisct1/minisign/releases/download/0.11/minisign-0.11-linux.tar.gz" EXPECTED_MINISIGN_HASH="f0a0954413df8531befed169e447a66da6868d79052ed7e892e50a4291af7ae0" if ! command -v minisign >/dev/null 2>&1; then echo "Lade gepinnten Minisign-Release herunter: $MINISIGN_URL" curl -fsSL "$MINISIGN_URL" -o minisign.tar.gz ACTUAL_HASH=$(sha256sum minisign.tar.gz | awk '{print $1}') if [ "$ACTUAL_HASH" != "$EXPECTED_MINISIGN_HASH" ]; then echo "KRITISCHER SICHERHEITSFEHLER: Minisign SHA-256 Pruefsumme ungueltig! Erwartet: $EXPECTED_MINISIGN_HASH, Erhalten: $ACTUAL_HASH" >&2 exit 1 fi echo "Minisign SHA-256 Integritaet erfolgreich verifiziert ($ACTUAL_HASH)." mkdir -p minisign-bin tar -xzf minisign.tar.gz -C minisign-bin rm -f minisign.tar.gz MINISIGN_EXE="./minisign-bin/minisign-linux/x86_64/minisign" chmod +x "$MINISIGN_EXE" else MINISIGN_EXE="minisign" fi TAG="${{ gitea.ref_name }}" KEY_FILE="sanctum-ci-release.key" trap 'rm -f "$KEY_FILE"' EXIT printf "%s" "$MINISIGN_SECRET_KEY" > "$KEY_FILE" "$MINISIGN_EXE" -S -s "$KEY_FILE" -m "dist/SHA256SUMS.txt" -W -x "dist/SHA256SUMS.txt.minisig" -t "version:${TAG}" if [ ! -f "dist/SHA256SUMS.txt.minisig" ]; then echo "Minisign-Signierung fehlgeschlagen!" >&2 exit 1 fi - name: Create Gitea Release uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1 with: files: | dist/*.zip dist/*.tar.gz dist/sanctum dist/sanctum.exe dist/SHA256SUMS.txt dist/SHA256SUMS.txt.minisig body_path: CHANGELOG.md draft: false prerelease: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}